# system.tag.writeAsync() requires callback to be named "callBack" in 8.0.14

**URL:** <https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768>\
**Category:** Ignition\
**Created:** [July 16, 2020, 1:47pm UTC](https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768 "2020-07-16T13:47:21Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [July 16, 2020, 1:47pm UTC](https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768/1 "2020-07-16T13:47:21Z")

</div>

Whenever I try to execute a callback with a name other than `callBack` (I cant even use `callback`) it fails showing that the global name is not defined.

Is this a bug, or is there a reason that the callback function specifically needs to be named and typed that way?

i.e. This works:

```auto
tagPath = "[Testing]Lines/Icing/Equipment/Mixer/State"

class tagWriter():
	def __init__ (self, tagPath):
		self.state = not system.tag.read(tagPath).value

	def callBack(self, aSyncReturn):
		print 'Tag write successful!'

	def tagWrite(self):
		system.tag.writeAsync([tagPath], [state], callBack)

writer = tagWriter(tagPath)
writer.tagWrite()

```

But this does not

```auto
tagPath = "[Testing]Lines/Icing/Equipment/Mixer/State"

class tagWriter():
	def __init__ (self, tagPath):
		self.state = not system.tag.read(tagPath).value

	def callback(self, aSyncReturn):
		print 'Tag write successful!'

	def tagWrite(self):
		system.tag.writeAsync([tagPath], [state], callback)

writer = tagWriter(tagPath)
writer.tagWrite()

```

Explicitly I need a completely different name for the callback, because its on a class that may have a handful of different callbacks after tag writes.

---

<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:** [July 16, 2020, 3:50pm UTC](https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768/2 "2020-07-16T15:50:03Z")

</div>

I think you already had a `callBack` variable in scope - were you testing in the script console? As is, neither of your examples will actually run - `tagPath`, `state`, and `callback` are not defined in the scope of the `tagWrite` function.  
I was able to get your example working with some modifications:

```python
tagPath = "[default]alarm"

class tagWriter():
	def __init__ (self, tagPath):
		self.tagPath = tagPath
		self.state = not system.tag.read(tagPath).value

	@staticmethod
	def callback(aSyncReturn):
		print 'Tag write successful!'

	def tagWrite(self):
		system.tag.writeAsync([self.tagPath], [self.state], tagWriter.callback)

writer = tagWriter(tagPath)
writer.tagWrite()

```

Unfortunately, the `writeAsync` callback argument isn’t defined very well - trying anything fancy will probably lead to `java.lang.ClassCastException: Cannot coerce value '<type>' into type: class org.python.core.PyFunction`. There’s not really any great ways around that, until/unless we patch the method internally. That’s why I had to use the `@staticmethod` decorator above - even calling `self.callback` isn’t a `PyFunction`, it’s a `PyClassMethod` or something similar, so the strict cast we have in our code won’t work.

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [July 16, 2020, 4:13pm UTC](https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768/3 "2020-07-16T16:13:24Z")

</div>

> [@paul-griffith](#):
>
> As is, neither of your examples will actually run - `tagPath` , `state` , and `callback` are not defined in the scope of the `tagWrite` function.

If I copy the text from my first one, it will run in the script console for, even with a fresh designer launch? I dont see the "Tag Write Successful" in the script console though, I see it in the regular console. I presumed this is because its executing in a separate thread associated with the designer instead of the script console.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/6/d654a4a73e0879e4f7700fabe0150b305302dfe1.png)

In regards to the rest of that, I can rename it with the change you made, however it loses the references to self in the callback function, which is not optimal as I actually need to reference some self variables in the real version of this script. In my real script library I just have it temporarily changed to `callBack` instead of `eventComplete` which is what I really need.

Is there any reason the above script runs for me and not you? Try setting your global scripting project to the one you're using, thats the only difference I could think of. Which I would assume is why the error that I see when using `callback` instead of `callBack` is the following:  
`NameError: global name 'callback' is not defined `

---

<div class="post-metadata">

**Author:** ![KMuldoon](https://avatars.discourse-cdn.com/v4/letter/k/839c29/32.png) [@KMuldoon](https://forum.inductiveautomation.com/u/KMuldoon)\
**Post date:** [July 16, 2020, 4:34pm UTC](https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768/4 "2020-07-16T16:34:49Z")

</div>

I know this is a bit of a workaround, but if you define the callBack function within the tagWrite definition, you can call your eventComplete method from that callBack with the references to self still intact.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/2/c2f404ae6005ae2046f6624fb4c2b4c178a538bc.png)

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [July 16, 2020, 4:39pm UTC](https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768/5 "2020-07-16T16:39:54Z")

</div>

This does feel like a bit of a workaround, but I recognize that it may just be a stipulation of the writeAsync function as paul mentioned above.

This works perfectly though, thank you!

---

<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:** [July 16, 2020, 4:43pm UTC](https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768/6 "2020-07-16T16:43:57Z")

</div>

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/6/e/6ed6d0f1f117ddb211bb2a1dc251b7e4ea77a9c4.png)  
This is what I get. Do you have a project library called `state`? This is what I would expect - `state` is unqualified when it’s referenced. `tagPath` happens to work in `tagWrite` because you defined it before you create your class - rewriting your sample to not define a `tagPath` variable then throws an exception about tagPath not existing:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/b/0b02fef435e9972be218972b24abe44e001b5367.png)  
Fixing that, then, leads to "`callBack` is not defined":  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/8/1/8120f735627e3327d4866fc21eac8666d0d88fbc.png)

Again, all expected behavior - this is all Python, and nothing to do with writeAsync at this point.  
The global scripting project can’t be a factor here, since we’re inside the scope of a particular project.

@KMuldoon’s suggestion is a good one - you can even improve it a bit using `lambda`:

```auto
class tagWriter():
	def __init__ (self, tagPath):
		self.tagPath = tagPath
		self.state = not system.tag.read(tagPath).value

	def callBack(self, aSyncReturn):
		print aSyncReturn, 'Tag write successful!'

	def tagWrite(self):
		system.tag.writeAsync([self.tagPath], [self.state], lambda r: self.callBack(r))

writer = tagWriter("[default]alarm")
writer.tagWrite()

```

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [July 16, 2020, 5:04pm UTC](https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768/7 "2020-07-16T17:04:50Z")

</div>

> [@paul-griffith](#):
>
> This is what I get. Do you have a project library called `state` ?

Interestingly I don't have a project library called `state` either...?

At this point with y'all's suggestions its working, just weird that I am seeing a different behavior than you are.

> [@paul-griffith](#):
>
> rewriting your sample to not define a `tagPath` variable then throws an exception about tagPath not existing

Weirdly mine also works without tagPath defined as well?

```auto
class tagWriter():
	def __init__ (self, tagPath):
		self.state = not system.tag.read(tagPath).value

	def callBack(aSyncReturn):
		print 'Tag write successful!'

	def tagWrite(self):
		system.tag.writeAsync([tagPath], [state], callBack)
writer = tagWriter("[Testing]Lines/Icing/Equipment/Mixer/State")
writer.tagWrite()

```

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/2/8/28d7ba145325f07e9af98bc633778aeb79d81688.png)

EDIT: @paul-griffith I PM'd you a copy of the project if it helps

---

<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 16, 2020, 5:47pm UTC](https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768/8 "2020-07-16T17:47:16Z")

</div>

> [@paul-griffith](#):
>
> Unfortunately, the `writeAsync` callback argument isn’t defined very well - trying anything fancy will probably lead to `java.lang.ClassCastException: Cannot coerce value '<type>' into type: class org.python.core.PyFunction` . There’s not really any great ways around that, until/unless we patch the method internally.

Oy! Please just use the standard PyObject.isCallable() and PyObject.\_\_call\_\_() / PyObject.\_jcall() methods. Those take care of all of the permutations. There's no excuse for not accepting `self.someCallback`.

):

---

<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:** [July 16, 2020, 8:49pm UTC](https://forum.inductiveautomation.com/t/system-tag-writeasync-requires-callback-to-be-named-callback-in-8-0-14/36768/9 "2020-07-16T20:49:26Z")

</div>

> [@pturmel](#):
>
> Oy! Please just use the standard PyObject.isCallable() and PyObject. **call** () / PyObject.\_jcall() methods. Those take care of all of the permutations. There’s no excuse for not accepting `self.someCallback` .

Indeed, that's exactly what I suggested in the bug ticket I filed this morning 🙂
