# Running into issue with derived tag expression

**URL:** <https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146>\
**Category:** Ignition\
**Tags:** ignition83\
**Created:** [February 24, 2026, 4:52pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146 "2026-02-24T16:52:54Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [February 24, 2026, 4:52pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/1 "2026-02-24T16:52:54Z")

</div>

We're planning to use derived tags to represent enumerated tags. We have a folder called "EnumTables" under the tag provider root and it contains Dataset tags to represent the translation table. Column 0 is the raw number and column 1 is the string representation. We want to store the EnumTable tag name in a custom "EnumTable" property on our derived tag so we can use it in other contexts and maintain it in one place.

I'm trying to use this expression:

```python
lookup(
  tag(concat("[~]EnumTables/", {[.]Run_Status 1.EnumTable})),
  {source},
  "Not Found",
  0,
  1
)

```

however the tags value keeps resolving to "1".

If I change the tag provider to:

```python
tag(concat("[OhioDemoTags]EnumTables/", {[.]Run_Status 1.EnumTable}))

```

it works correctly. Am I missing something?

---

<div class="post-metadata">

**Author:** ![MMaynard](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mmaynard/32/3366_2.png) [@MMaynard](https://forum.inductiveautomation.com/u/MMaynard)\
**Post date:** [February 24, 2026, 5:09pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/2 "2026-02-24T17:09:45Z")

</div>

I would move this over to a UDT def and have the table path be a parameter on the UDT itself.

---

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [February 24, 2026, 5:24pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/3 "2026-02-24T17:24:10Z")

</div>

We went down the route of UDTs but have since converted to raw tags as we found UDTs too constraining.

---

<div class="post-metadata">

**Author:** ![Nol](https://avatars.discourse-cdn.com/v4/letter/n/8e8cbc/32.png) [@Nol](https://forum.inductiveautomation.com/u/Nol)\
**Post date:** [February 24, 2026, 5:50pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/4 "2026-02-24T17:50:50Z")

</div>

Maybe post how you have EnumTable laid out and where your tags are located.

Edit: Misleading. [~] goes to the root. [.] goes relative to the tag

You could try this syntax and see if it gets you closer as I think it's a bit clearer. Note the write expression makes it bi-directional which you may not want for a run\_status.

On a side note using UDT's is probably going to make your life a lot easier if you use them correctly. Might be worth still looking into that.

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

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

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

---

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [February 24, 2026, 6:04pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/5 "2026-02-24T18:04:59Z")

</div>

Maybe I misunderstood this from the docs.

```python
`[~]` | Relative to the Tag Provider of the tag that is being bound (root node).

```

---

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [February 24, 2026, 6:07pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/6 "2026-02-24T18:07:05Z")

</div>

`[~]` refers to the Tag's Provider root. It replaces an explicit provider name and thus protects the tag path from "breaking" if the provider is renamed or if the tag is imported/exported/moved between different providers.

> **[Tag Paths | Ignition User Manual](https://www.docs.inductiveautomation.com/docs/8.3/platform/tags/tag-paths)**
>
> Tags and their properties can be referenced by a string-based path in many areas of Ignition, such as expressions and scripts. Each tag has a unique absolute path and often has many equivalent relative paths when referenced from other tags. In most...

---

<div class="post-metadata">

**Author:** ![Nol](https://avatars.discourse-cdn.com/v4/letter/n/8e8cbc/32.png) [@Nol](https://forum.inductiveautomation.com/u/Nol)\
**Post date:** [February 24, 2026, 6:22pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/7 "2026-02-24T18:22:31Z")

</div>

Whoops, I edited my comment. [.] is relative, [~] is root.

This syntax still works for what you want to do though:

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

---

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [February 24, 2026, 6:49pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/8 "2026-02-24T18:49:29Z")

</div>

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/f/ff76ba148ffcfd21bb92a0eb03f8f5401f61f84c.png)  
The correct output should be "1: Running" and yet I'm just getting "1".

---

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [February 24, 2026, 6:50pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/9 "2026-02-24T18:50:57Z")

</div>

I'm trying to dynamically build the tag using the custom property as well hence the

```python
tag(concat("[~]EnumTables/", {[.]Run_Status 1.EnumTable}))

```

---

<div class="post-metadata">

**Author:** ![lane.duncan](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lane.duncan/32/83700_2.png) [@lane.duncan](https://forum.inductiveautomation.com/u/lane.duncan)\
**Post date:** [February 25, 2026, 7:39am UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/10 "2026-02-25T07:39:42Z")

</div>

> [@Ethan\_Brown](#):
>
> We went down the route of UDTs but have since converted to raw tags as we found UDTs too constraining.

If you want to avoid UDT's but still retain some scalability consider a centralized Gateway Tag Change script. This way you get a few more tools (like custom error logging/handling) and you can somewhat limit the places where you will have to make the inevitable changes.

Add a custom string to each tag called enum:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/b/0b9dcd338411b205d1b30707140571469d208cb5.png)

Then add a single Tag Change script for all the similar devices. Something like this:

```python
def onTagChange(initialChange, newValue, previousValue, event, executionCount):
	import traceback
	logger = system.util.getLogger("EnumTestTagChangeScript") 
	try:
		enumList = ["Burger","Taco","Sushi","Pizza","Soup"]
		enumTagPath = str(event.tagPath) + ".enum"
		tagValue = event.currentValue.value

		enumString = enumList[tagValue]
		
		system.tag.writeBlocking([enumTagPath], [enumString],10)
	
	except:
	    system.tag.writeBlocking([enumTagPath], "Error",10)
	    message = traceback.format_exc() 
	    logger.error(message)

```

Then add the tags:

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

The other bonus is it will cut your tag count in half.

---

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [February 25, 2026, 10:50pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/11 "2026-02-25T22:50:39Z")

</div>

This would be nice if you didn’t have to manually add each tag to the script which it looks like you have to. That also won’t scale nicely when you’re bringing on an entire new CTB.  
We poll a raw numeric value from a field device and then display the enumerated value to operators.

---

<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:** [February 25, 2026, 11:14pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/12 "2026-02-25T23:14:15Z")

</div>

Converting status integers from tags into corresponding strings is not a job for tags. This belongs in your user interface. See this entire topic:

> [@Slow Expression Tags](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/14):
>
> Yes. Where you must use them, you should time them with java.lang.System.nanoTime() and log when \>5ms. So you can focus on removing the worst offenders. Ideally, do not run database or network operations, or make system calls that do database or network operations. Make sure the tags are in event driven mode, so they only run when a reference changes. This should not be in an expression tag at all. It will run when no one is looking at it (useless), and cannot be internationalized for mu…

In that case it is `runScript()` in expression tags, where here it is scripted lookups, but it is the same fundamental design error.

---

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [February 26, 2026, 3:21pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/13 "2026-02-26T15:21:36Z")

</div>

By doing it on your user interface, wouldn't every screen in user interface need to check if a tag needs to be enumerated?

---

<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:** [February 26, 2026, 3:22pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/14 "2026-02-26T15:22:59Z")

</div>

Yes. If you have thousands of tags and only dozens of clients, it's a win to have the UI do it. While enabling internationalization at a later time.

---

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [February 26, 2026, 3:30pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/15 "2026-02-26T15:30:48Z")

</div>

That seems inefficient and cumbersome. Every UI component, from a text box to a grid cell, will need to constantly look if the tag value it's representing needs to be enumerated.

---

<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:** [February 26, 2026, 4:07pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/16 "2026-02-26T16:07:35Z")

</div>

> [@Ethan\_Brown](#):
>
> Every UI component

Why?

Make embeddable views or templates based on the expectation of what they will display. The `.enum` custom property should only be indirect bound in UI components that expect it.

---

<div class="post-metadata">

**Author:** ![lane.duncan](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lane.duncan/32/83700_2.png) [@lane.duncan](https://forum.inductiveautomation.com/u/lane.duncan)\
**Post date:** [February 27, 2026, 3:55am UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/17 "2026-02-27T03:55:48Z")

</div>

> [@pturmel](#):
>
> thousands of tags and only dozens of clients

I can predict that you will be asking “Why is my application so slow and need so much expensive RAM” a year from now. We have all dealt with scaling issues.

With thousands of tags, efficient processing at scale only has so many tools you can throw at it, because the tag count is what it is.

You have been given many suggestions for better tag processing, like using UDT’s and only doing work if the value changes.

Phil has also suggested building an efficient UI, which is arguably the most important step in the design process.

Ignition has many incredible UI tools which, when used correctly with a UDT and efficient tag processing, scales incredibly well.

You really should take a hard look at other tools to accomplish your goals.

---

<div class="post-metadata">

**Author:** ![Ethan\_Brown](https://avatars.discourse-cdn.com/v4/letter/e/9de053/32.png) [@Ethan\_Brown](https://forum.inductiveautomation.com/u/Ethan_Brown)\
**Post date:** [March 2, 2026, 6:52pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/18 "2026-03-02T18:52:36Z")

</div>

I care less about the UI and more about our data pipeline that gets data out and set points back into Ignition from our internal applications.

---

<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 4, 2026, 6:54pm UTC](https://forum.inductiveautomation.com/t/running-into-issue-with-derived-tag-expression/114146/19 "2026-03-04T18:54:06Z")

</div>

I can’t explain why your [~] relative reference is breaking.

Ignoring the good advice to translate as much as possible in the UI (even if POU is outside Ignition)…

_Side note_: I would put the **entire path** to the enumeration table in the custom property, instead of just a part of the path. I would want the flexibility to look at the enum table wherever it exists in the tag database, be able to utilize relative referencing ([.], [~], etc.), and not be confined to a single folder of a provider. Additionally, I typically prefer an array tag, except for cases where large gaps in the enum table exist (an Engine Annunciator Fault Code table, for example). I would not utilize any script to perform this transform, regardless of UI-based or tag-based solution. I would also use an expression tag, not a derived tag, as I can’t envision a reason to ever write a value back to this (or the source) tag. To each-their-own here.

See below for a good reference to options for building tag paths within expressions:

> **[Tag Paths | Ignition User Manual](https://www.docs.inductiveautomation.com/docs/8.3/platform/tags/tag-paths)**
>
> Tags and their properties can be referenced by a string-based path in many areas of Ignition, such as expressions and scripts. Each tag has a unique absolute path and often has many equivalent relative paths when referenced from other tags. In most...

Near the bottom, you’ll see the syntax to reference a custom property of ‘this tag’ (hereon, ‘this’ will refer to a tag that is intended to contain the resultant string post-lookup):  
`{this.name}`

To retrieve your custom property from ‘this tag’:  
`{this.myCustomProperty}`

To have access to the enum table (assuming its entire path is contained in the value of ‘myCustomProperty’), wrap the value of the prop in a tag() expression:  
`tag({this.myCustomProperty})`

To [access a specific row of the array](https://www.docs.inductiveautomation.com/docs/8.3/platform/tags/tag-paths#array-type-tag-paths) tag:  
`tag({this.myCustomProperty})[<row_number>]`

If using another tag’s value (in this example, the tag’s name is ‘EnumValue’, residing in the same folder)  
`tag({this.myCustomProperty})[{[.]EnumValue}]`

To [access a specific row & column of a dataset](https://www.docs.inductiveautomation.com/docs/8.3/platform/expression-language-and-syntax#dataset-access) tag:  
`tag({this.myCustomProperty})[<Row_Index>, <"Column_Name" -OR- Column_Index>`  
`tag({this.myCustomProperty})[{[.]EnumValue.value}, "Text"]`

Or, if there are gaps in your dataset, and you must use [lookup](https://www.docs.inductiveautomation.com/docs/8.3/appendix/expression-functions/logic/lookup):  
`lookup(tag({this.myCustomProperty}), {[.]EnumValue.value}, “ERROR”, "Value", "Text")`  
You can also substitute column indexes if desired: “Value” –\> 0, and “Text” –\> 1.

With the above, a ‘myCustomProperty’ value of either ‘[~]…’ or ‘[]…’ should function as expected.
