# \[BUG\] Tag writes that weren't permitted to write due to user permissions still get recorded in audit log

**URL:** <https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [July 23, 2025, 2:40am UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803 "2025-07-23T02:40:37Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [July 23, 2025, 2:40am UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/1 "2025-07-23T02:40:37Z")

</div>

An end user just noticed that if a tag has write permissions set on it and the tag is bidirectionally bound to a toggle switch (in Perspective for example), and a user who doesn't have the write permission tries to toggle the switch, it correctly doesn't write and shows a warning message. However if you check the audit log, there will be a "tag write" action for that tag and user indicating the write went through which is extremely deceptive and can destroy the credibility of the log.

---

<div class="post-metadata">

**Author:** ![nideyijuyidong](https://avatars.discourse-cdn.com/v4/letter/n/7cd45c/32.png) [@nideyijuyidong](https://forum.inductiveautomation.com/u/nideyijuyidong)\
**Post date:** [July 23, 2025, 3:14am UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/2 "2025-07-23T03:14:31Z")

</div>

Yes, I reproduced this problem on 8.1.48.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 23, 2025, 11:43am UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/3 "2025-07-23T11:43:47Z")

</div>

Did you open a support ticket?

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [July 23, 2025, 1:01pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/4 "2025-07-23T13:01:35Z")

</div>

Yes I did 👌

---

<div class="post-metadata">

**Author:** ![dbronish](https://avatars.discourse-cdn.com/v4/letter/d/74df32/32.png) [@dbronish](https://forum.inductiveautomation.com/u/dbronish)\
**Post date:** [March 12, 2026, 4:58pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/5 "2026-03-12T16:58:14Z")

</div>

Can you please provide an update and/or link to the support ticket? I’ve just encountered this same issue.

---

<div class="post-metadata">

**Author:** ![Chris\_Bingham](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@Chris\_Bingham](https://forum.inductiveautomation.com/u/Chris_Bingham)\
**Post date:** [March 17, 2026, 12:25pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/6 "2026-03-17T12:25:38Z")

</div>

To me, this points to an issue in the UI or project configuration. The audit log shouldn’t be used as a source of verification that a write was successful, only that the write was attempted. In my opinion, that action SHOULD be recorded.

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [March 17, 2026, 12:32pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/7 "2026-03-17T12:32:16Z")

</div>

Fair about recording an attempt, but then a log for the rejection of the write should be present as well which I take it is not the case.

---

<div class="post-metadata">

**Author:** ![Chris\_Bingham](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@Chris\_Bingham](https://forum.inductiveautomation.com/u/Chris_Bingham)\
**Post date:** [March 17, 2026, 12:38pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/8 "2026-03-17T12:38:12Z")

</div>

Perhaps. However, there’s a thousand ways that a write could ‘fail’. Tag permissions, provider permissions, service security, poor network connection to an end device, rejection by the end device, accepted but immediately overwritten in the end device…

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [March 17, 2026, 12:41pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/9 "2026-03-17T12:41:54Z")

</div>

Right but if we go with your idea that the attempt should be recorded no matter what (which I do agree with) what there _must_ be some indication if it was not succesful otherwise @nminchin original point stands that the log becomes unreliable. Reason can be whatever, but tell me it didn’t go through. A lot of those reasons are probably catchable and recordable too, certainly permissions ones, and if its not then a “failed write reason unknown” at least keeps the audit trail 100% truthful about what happened, user tried to write, something bad happened we don’t know what but the write didn’t go through. Without that it just looks like the user wrote when they didn’t.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [March 17, 2026, 1:03pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/10 "2026-03-17T13:03:59Z")

</div>

> [@bkarabinchak.psi](#):
>
> Reason can be whatever, but tell me it didn’t go through.

Confirmation is covered by historization. Capturing write rejection reasons is near impossible, since some can be external. There's no replacement for proper use of `try` clauses and inspection of returned quality codes.

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [March 17, 2026, 1:48pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/11 "2026-03-17T13:48:42Z")

</div>

Sounds like the best thing to do is just write your own `writeTags` function that examines the result and audits failures appropriately and call that for all your tag writes instead? In scripts at least

Though that doesn’t really help in the OP case where it was due to tag binding on a UI component.

Are you saying if you have audit trails enabled without the historian module your SOL to create such a trail (user wrote and the confirmation of if the write went through or not)?

---

<div class="post-metadata">

**Author:** ![Chris\_Bingham](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@Chris\_Bingham](https://forum.inductiveautomation.com/u/Chris_Bingham)\
**Post date:** [March 17, 2026, 2:42pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/12 "2026-03-17T14:42:59Z")

</div>

In my opinion, the first step is to update the UI to disallow the write in the first place. The user should know whether-or-not they have permission to write before they attempt to do so. Tags have a “[.CanWrite](https://www.docs.inductiveautomation.com/docs/8.1/platform/tags/tag-properties#runtime-properties)” property (value is unique per-client) and can be bound in the UI to disable the entry in the first place. Note that this doesn’t capture all possible scenarios as might be required from a proper audit trail (those previously listed, also tag deadband preventing a value update, floating point representation error after successful write, etc.).

I’ve not built a proper audit tool personally (despite my own empty threats to do so). But, I have spent enough time compiling data for other parties (managers, engineers, lawyers) that I’ve resolved that:

1. It’s a difficult problem to solve for ‘all users’ & ‘all use-cases’.
2. I’m grateful that I have too much data to work with, instead of not enough.
3. Despite 1 & 2, I’m still frustrated every time I have to handle all of the useless data in the audit logs.

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [March 17, 2026, 5:39pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/13 "2026-03-17T17:39:19Z")

</div>

I agree to your point in regard to the UI not even being allowed to write and using a that to not allow a non-permissable user to even attempt to write.

Though as you said there are a ton of reasons something could fail not related to any permissions. So you could have a person who does have permissions try to wirte, it fails and the audit trail looks all good.

I personally don’t particulary care about _why_ being logged to the audit trail for UI binding writes personally just if it failed because what I am I thinking about is getting a call to come in the day(s) after to check something out - Hey we pressed this button but the process didn’t start. If I look at the audit logs and see a tag write and nothing else what else can I interpret but that the tag was written to and something happened on the PLC side of things.

But If i see tag write and a failure (without any reason listed), I would start elsewhere - how is the opc-ua server, the ignition connection to the opc-ua, the network etc. I can’t say anything for certain just off the audit trail but it would help me not go on a wild goose chase immediately where I assumed the tag was written to when it was not.

Thats why I think even without auditing a reason if possible it would be nice to record a failure. Though unfortunately doesn’t seem feasible according to Phil.

---

<div class="post-metadata">

**Author:** ![Chris\_Bingham](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@Chris\_Bingham](https://forum.inductiveautomation.com/u/Chris_Bingham)\
**Post date:** [March 17, 2026, 7:15pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/14 "2026-03-17T19:15:05Z")

</div>

Unsolicited, yet unapologetic tangent:

I do wish there were an optional argument on `system.tag.write*` functions which resembles the functionality of `skipAudit` arg on the [system.db.runPrepUpdate](https://www.docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions/system-db/system-db-runPrepUpdate) function. I envision that this arg would give someone a _better_ ability to build an audit system which matches their needs.

I believe @nminchin has a post about this feature request:

> [@\[FEATURE\] Add option to skip audit log in system.tag.write functions](https://forum.inductiveautomation.com/t/feature-add-option-to-skip-audit-log-in-system-tag-write-functions/61039):
>
> I need to add previous value into the audit log, so I essentially need to create my own wrapper functions for the two system.tag.write\* functions and insert my own entries into the audit log table to which I’ve added a new ACTION\_VALUE\_PREVIOUS field. These functions both write into the audit log though which I would like to be able to skip, like is possible with the system.db.\*Update functions. PS. I already have a feature suggestion for actually recording the previous values by default, but I…

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [March 17, 2026, 7:45pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/15 "2026-03-17T19:45:05Z")

</div>

> [@Chris\_Bingham](#):
>
> resembles the functionality of `skipAudit` arg on the [system.db.runPrepUpdate](https://www.docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions/system-db/system-db-runPrepUpdate) function

_Psssssst! Not implemented!_

> [@Automation Professionals' Integration Toolkit Module](https://forum.inductiveautomation.com/t/automation-professionals-integration-toolkit-module/74934/90):
>
> In the RPC message, it's just adding a boolean true for the skipAudit arg on the outgoing Message, which is parsed in the RPC handling (com.inductiveautomation.ignition.gateway.servlets.gateway.functions.AbstractUpdateQuery). On the gateway, skipAudit is a no-op (the call is simply never audited), as far as I can tell.

---

<div class="post-metadata">

**Author:** ![Chris\_Bingham](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@Chris\_Bingham](https://forum.inductiveautomation.com/u/Chris_Bingham)\
**Post date:** [March 18, 2026, 3:47pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/16 "2026-03-18T15:47:18Z")

</div>

🤔

I just tested and confirm that running the `runPrepUpdate` function with `skipAudit=False` DOES add an entry to the audit log. I also confirm that running the same script with `skipAudit=True` DOES NOT add an entry to the audit log.

I suppose there is some ambiguity in his statement:

> [@Automation Professionals' Integration Toolkit Module](https://forum.inductiveautomation.com/t/automation-professionals-integration-toolkit-module/74934/90):
>
> the call is simply never audited

There’s a recent post on lack of audit w.r.t. named queries:

> [@\[IGN-15680\]Way to audit named queries?](https://forum.inductiveautomation.com/t/ign-15680-way-to-audit-named-queries/114416):
>
> Using 8.1.47 vision with auditing turned onto a database datasource. I only just noticed this - queries run via system.db.runPrepUpdate queries gets audited in full to the audit log ie the full query itself is logged which is nice for seeing exactly what happened. The same does not happen when running UPDATE/INSERT statements via runNamedQuery in fact I don’t see anything. I would have expected either the full query or even just the namedQueryPath and the params (though the full query would b…

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [March 18, 2026, 3:50pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/17 "2026-03-18T15:50:18Z")

</div>

> [@Chris\_Bingham](#):
>
> confirm that running the `runPrepUpdate` function

What scope were you calling from?

(I will obviously have to revisit this in my toolkit.)

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [March 18, 2026, 3:56pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/18 "2026-03-18T15:56:02Z")

</div>

Yeah, my earlier post was ambiguous. Calling scope matters.  
DB functions from client/designer scope hit special RPC methods that "understand" the `skipAudit` flag.  
Direct DB system function calls when you're already in gateway scope don't do anything with the skipAudit parameter.

---

<div class="post-metadata">

**Author:** ![Chris\_Bingham](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@Chris\_Bingham](https://forum.inductiveautomation.com/u/Chris_Bingham)\
**Post date:** [March 18, 2026, 4:01pm UTC](https://forum.inductiveautomation.com/t/bug-tag-writes-that-werent-permitted-to-write-due-to-user-permissions-still-get-recorded-in-audit-log/108803/19 "2026-03-18T16:01:14Z")

</div>

Good to know! As can be assumed, I did execute from script console for my quick test above. Somewhat unrelated - but I’ve also confirmed audit entries via Database Query Browser (Designer) when query type is “Update”.
