Tag import works properly through GUI, but get error when trying through scripting

I can import a large XML just fine through the import wizard on the designer. However, I made a perspective screen to import through a file upload component. Here is my script on the file upload action:

def runAction(self, event):
	PATH = "C:\\alarms.xml"
	try:
		event.file.copyTo(PATH)
		system.tag.importTags(PATH, "[edge]Alarms", "o")
	except:
		self.clearUploads()
		Library.popup.showException()

Normally if there is an exception (like event.file.copyTo fails) the except line will run a user script showException() which causes the exception message to popup. This does not occur, instead I have to go to gateway logs to see the exception message. The exception message is from tag.management.provider and contains

com.inductiveautomation.ignition.gateway.tags.importexport.ImportException: Udt definitions can only be imported in the UDT Definitions tab.

at com.inductiveautomation.ignition.gateway.tags.TagProviderImpl.lambda$validateTypePath$25(TagProviderImpl.java:1211)

at java.base/java.util.ArrayList.forEach(Unknown Source)

at com.inductiveautomation.ignition.gateway.tags.TagProviderImpl.validateTypePath(TagProviderImpl.java:1201)

at com.inductiveautomation.ignition.gateway.tags.TagProviderImpl.lambda$importTagsAsync$24(TagProviderImpl.java:1155)

at com.inductiveautomation.ignition.gateway.tags.TagProviderImpl.lambda$exec$4(TagProviderImpl.java:475)

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.base/java.lang.Thread.run(Unknown Source)

I have verified that the uploaded XML is getting copied to the "C:\alarms.xml" path. What could be the issue?

You are importing UDTs not tags. If these are really meant to be UDTs then your "[edge]Alarms" tag folder will need to be changed to the UDT folder.

These are instances of UDTs, but the UDT is already defined in the tag provider. Here is a sample of the XML

<Tags MinVersion="8.0.0" locale="en_US">
<Tag name="Tag Name Here" type="Folder">
<Tags>
<Tag name="0" type="UdtInstance">
<Property name="typeId" type="String">HmiMessageData</Property>
<Parameters>
<Property name="alarmMsg" type="String" boundValueType="parameter">Alarm Message Here</Property>
<Property name="tagPath" type="String">plc.path.to.tag</Property>
<Property name="alarmName" type="String">Alarm Name Here</Property>
<Property name="priority" type="Integer">4</Property>
</Parameters>
<Tags>
<Tag name="bActive" type="AtomicTag"/>
</Tags>
</Tag>
...

Plain jython try: - except: clauses cannot catch Java exceptions, because java exceptions have their own class hierarchy. You need two except clauses, like so:

from java.lang import Throwable

def someFunction(....):
	try:
		something()
	except Throwable, t:
		... do something with java throwable/exception t ...
	except Exception, e:
		... do something with jython exception e ...

Maybe take a look at your XML and see if there is anything that references

UdtType

That doesn't work either. Might be because system.tag.importTags() executes on a separate thread?

No instances of UdtType here's what it looks like when I import through the interactive GUI on the designer.
image

What part doesn't work? Catching the exception, or showing the exception in Perspective?

(I just use loggers, fwiw. Showing exceptions to Perspective clients can leak sensitive information.)

If the latter, make sure you pass session and page IDs to your separate thread so you can target a popup in spite of being asynchronous.

Catching the exception. I made both exception statements clear the upload component, but the upload component does not clear when the import fails.

Something new should be showing in your logs now. Did you look?

(Have you gotten any tag import to work this way? If so, test both with a known good json file and the problem json file.)

Ok importing a single tag worked. Looking closer at my original xml there was a single empty folder which I think is screwing the whole import up. I'll make sure in my alarm export tool to delete empty folders.

Going back to the exception catching though, it still never goes into the except statements. I do see the exception messages on the gateway logger.

My example presumed you were delegating to a project library script function. (You should, always.) If not, you need that import within the action.

Show your updated code.

I'll eventually have it in a library script but just had it directly in the run action script for testing.

def runAction(self, event):
	from java.lang import Throwable
	PATH = "C:\\alarms.xml"
	try:
		event.file.copyTo(PATH)
		system.tag.importTags(PATH, "[default]AlarmsNew", "o")
	except Throwable, t:
		self.clearUploads()
		#Todo: add error message to screen
	except Exception, e:
		self.clearUploads()
		#Todo: add error message to screen

With that code, the original exception or throwable is lost. Please log it in addition to attempting to clear your uploads.

If you are still getting logged exceptions, take a close look at them--they might be different. And show one here, please (with the stacktrace expanded), or paste from your wrapper log (using code styling).

I'm confused, why not just strip the try/except for now and read the error the designer throws?

1 Like

After playing around with it, I can check the return value. It returns a quality code of Error_Exception in the return array with a diagnostic message if the import fails. I guess importTags does its own exception handling, that's why my exception statements were never getting executed.

1 Like