# Expression Language Misunderstanding: indexOf()

**URL:** <https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [May 15, 2026, 1:58pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551 "2026-05-15T13:58:15Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Wesley\_Waters1](https://avatars.discourse-cdn.com/v4/letter/w/4bbf92/32.png) [@Wesley\_Waters1](https://forum.inductiveautomation.com/u/Wesley_Waters1)\
**Post date:** [May 15, 2026, 1:58pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/1 "2026-05-15T13:58:15Z")

</div>

I have the following Expression Structure:

```python
{
"Valves":[
0:Open
1:Closed
2:Closed
...
]

```

I want to return true if any of the valves are open

When I do the following:

```python
{value}["Valves"][0] = "Open"

```

Result: true

When I do the following:

```python
indexOf({value}["Valves"],"Open")

```

Result: -1

Can someone explain what I am doing wrong or what assumptions I have that are incorrect? I also tried checking the typeOf({value}["Valves"][0] and it is a string...

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [May 15, 2026, 2:04pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/2 "2026-05-15T14:04:57Z")

</div>

`{value}["Valves"]` is not `{value}["Valves"][0]`.

`indexOf()` does not find the index of a string in a list, it finds the index of a substring in a string.

What are you trying to accomplish?

---

<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:** [May 15, 2026, 2:08pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/3 "2026-05-15T14:08:30Z")

</div>

I would use my Toolkit's [where()](https://www.automation-pros.com/toolkit/doc/iteration.html#where) iterator, wrapped in `len()`. Like so:

```python
len(
    where(
        {value}['Valves'],
        it() = 'Open'
    )
) > 0

```

(I would also collapse your expression structure to use my `asList()` and nest it directly in the final expression. Avoid the transform overhead.)

---

<div class="post-metadata">

**Author:** ![Wesley\_Waters1](https://avatars.discourse-cdn.com/v4/letter/w/4bbf92/32.png) [@Wesley\_Waters1](https://forum.inductiveautomation.com/u/Wesley_Waters1)\
**Post date:** [May 15, 2026, 2:08pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/4 "2026-05-15T14:08:43Z")

</div>

Oh duh, that makes sense. I am looking for if any of the values are "Open" then I want to return True

---

<div class="post-metadata">

**Author:** ![Wesley\_Waters1](https://avatars.discourse-cdn.com/v4/letter/w/4bbf92/32.png) [@Wesley\_Waters1](https://forum.inductiveautomation.com/u/Wesley_Waters1)\
**Post date:** [May 15, 2026, 2:09pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/5 "2026-05-15T14:09:52Z")

</div>

Is a native clean solution not available?

---

<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:** [May 15, 2026, 2:10pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/6 "2026-05-15T14:10:24Z")

</div>

> [@Wesley\_Waters1](#):
>
> available

No. My Toolkit closes many gaps in the native expression language, especially when dealing with lists, maps, and variable-length objects.

---

<div class="post-metadata">

**Author:** ![Wesley\_Waters1](https://avatars.discourse-cdn.com/v4/letter/w/4bbf92/32.png) [@Wesley\_Waters1](https://forum.inductiveautomation.com/u/Wesley_Waters1)\
**Post date:** [May 15, 2026, 2:22pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/7 "2026-05-15T14:22:02Z")

</div>

I'm bummed that there is no clean native solution. I am going to install your module to test it out, but I am unable to do a gateway restart at this time so I cannot test it out. Thank You for your work on this module.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [May 15, 2026, 3:18pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/8 "2026-05-15T15:18:27Z")

</div>

Probably the best you can get in a single binding without Phil's module, is to add a script transform.

```python
return any(valve == 'Open' for valve in value)

```

Phil's module is worth it, you will not know what you did without it.

---

<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:** [May 15, 2026, 3:37pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/9 "2026-05-15T15:37:30Z")

</div>

> [@lrose](#):
>
> Phil's module is worth it

😊

(Worth the bureaucratic trouble, if any, only, as it is **free**.)

---

<div class="post-metadata">

**Author:** ![travisaggiebrown](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/travisaggiebrown/32/85824_2.png) [@travisaggiebrown](https://forum.inductiveautomation.com/u/travisaggiebrown)\
**Post date:** [May 18, 2026, 8:06pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/10 "2026-05-18T20:06:27Z")

</div>

am I missing something? I tried to recreate your issue and was unable to.

I created a property:

{  
"valves":  
[  
"open",  
"closed",  
"closed"  
]  
}

I created a binding to that and ran this expression:

```python
indexOf({value}['valves'], 'open')

```

it returns 0 and when I remove the string open from the list it returns -1, which is the intended result for what you described

this should natively work if you just need to check if it is contained in the list and not how many

---

<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:** [May 18, 2026, 8:17pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/11 "2026-05-18T20:17:08Z")

</div>

I think the list behavior was added recently. @paul-griffith would know.

---

<div class="post-metadata">

**Author:** ![travisaggiebrown](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/travisaggiebrown/32/85824_2.png) [@travisaggiebrown](https://forum.inductiveautomation.com/u/travisaggiebrown)\
**Post date:** [May 18, 2026, 8:26pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/12 "2026-05-18T20:26:33Z")

</div>

I don't think it's that recent because according to the 8.1 documentation [indexOf | Ignition User Manual](https://www.docs.inductiveautomation.com/docs/8.1/appendix/expression-functions/logic/indexOf) it says that it can take a list or tuple and it shows that documentation was last updated jan 13, 2025.

---

<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:** [May 18, 2026, 8:34pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/13 "2026-05-18T20:34:50Z")

</div>

Interesting. "As of version 8.1.8". That was quite a while ago. Maybe there's a nuance/bug to expression structure bindings?

---

<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:** [May 18, 2026, 9:42pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/14 "2026-05-18T21:42:39Z")

</div>

Yeah, it's expression structure bindings.

Most other contexts, if you're dealing with a list of values, it's a QualifiedValue over a list.  
Expression structure bindings chained into a transform, for whatever reason, are a QualifiedValue containing a list _of qualified values_.  
The `indexOf` function implementation unpacks the right hand side 'needle' into `"Open"`, but doesn't touch the lhs/haystack, so the index checking doesn't work.

We already have code to unpack arrays of nested qualified values, we just need to add a branch for lists.

---

<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:** [May 18, 2026, 9:47pm UTC](https://forum.inductiveautomation.com/t/expression-language-misunderstanding-indexof/115551/15 "2026-05-18T21:47:48Z")

</div>

Ah. Run it through my `unQualify()` function.
