Write to client memory tag fails in tag event, yet succeeds in client timer event

I can write to a client memory tag from a client timer script, but not from the value-changed script for a tag.

Scenario:
A fresh install of Ignition 7.9.5, with one simple project.
A client timer script executes at 2 second intervals. (Was 1 second intervals for a while.)
The timer script:
– Increments GenericSimulator.WriteableInteger1, so I know the timer script is running.
– Toggles GenericSimulator.WriteableBoolean1.
– Optionally toggles client string tag Info.
The write to the Info tag always succeeds.

The value-changed script in GenericSimulator.WriteableBoolean1:
– Toggles GenericSimulator.WriteableBoolean2, so I know the WriteableBoolean1 script is running.
– Optionally toggles client string tag Info.
The write to the Info tag never succeeds. There is no mention of the write in the wrapper log.

It is the same line of code in the two scripts.
I use GenericSimulator.WriteableInteger2 to determine which script writes to the Info tag, so there is no contention. (I also ran the test by alternately disabling the scripts, with unconditional writes; same result.)

Why would the same line of code work in the client timer script, and fail in the tag value-changed script?

Separately, and seemingly unrelated, the wrapper log has this entry at one second intervals:
– Created auto-backup of internal database “config.idb” in 893 ms

This is the code in the timer script:
iValue1 = system.tag.read(‘WriteableInteger1’).value
system.tag.write(‘WriteableInteger1’, iValue1 + 1)

iValue2 = system.tag.read(‘WriteableInteger2’).value

if system.tag.read(“WriteableBoolean1”).value:
system.tag.write(“WriteableBoolean1”, False)
if iValue2 == 1:
system.tag.write("[Client]Status/Info", “False”)
else:
system.tag.write(“WriteableBoolean1”, True)
if iValue2 == 1:
system.tag.write("[Client]Status/Info", “True”)

This is the code in the value-changed script for GenericSimulator.WriteableBoolean1:
iValue2 = system.tag.read(‘WriteableInteger2’).value

if currentValue.value:
	system.tag.write("WriteableBoolean2", True)
	if iValue2 == 0:
		system.tag.write("[Client]Status/Info", "True")
else:
	system.tag.write("WriteableBoolean2", False)
	if iValue2 == 0:
		system.tag.write("[Client]Status/Info", "False")

Tags and tag value change scripts all live and execute in the gateway scope.

Your client tag only exists in the client, so you can only interact with it from the timer script running in the client.

Interesting.
I’ll need to adjust my thinking about the interaction between tags and project.
First thought is to use gateway scoped memory tags.
I see that gateway tags are shared among all clients.
For tags that I want to protect, can I use roles restrict access to a certain project? (A mostly rhetorical question at this point; I haven’t read that section in the manual yet.)

Surprisingly, I have the same problem with an INSERT into my database. The prepared statement method works in the client timer script, but not in the OPC tag value-changed script. Surprising because the database connection is in the gateway.

(Thanks for answering on the weekend.)

Tag events, as part of a tag, do not belong to any project, and so have no “default database”. All database operations in a global gateway context must specify which database connection to use.
There are three contexts that a programmer must consider when using Ignition:

  1. Client/designer context. Client tags, global jython variables, windows, and component all exist independently in each client. Gateway tags can trigger project-specific client events, which can use both project.* and shared.* scripts. Database operations use the project’s default connection if none specified, and gateway tag operations use the project’s default provider.
  2. Gateway project context. Project-specific gateway events and transaction groups exist here. Client tags, windows, and components do not exist. Tag change scripts and other events in this context can use both project.* and shared.* scripts. Database operations in these scripts use the project’s default connection if none specified, and gateway tag operations use the project’s default provider.
  3. Gateway global aka shared context. Tag events exist here. Client tags, windows, and components do not exist. Only shared.* scripts are accessible. All database operations must specify a connection. All other tag operations must specify a provider.

Adding the database connection name solved the problem.
Thanks.
I get the general idea of the three contexts. I’ll study the manual and try more test code, especially with regard to the relationship between gateway tag events and project scripts.