# Client tag expression with hasRole NPE

**URL:** <https://forum.inductiveautomation.com/t/client-tag-expression-with-hasrole-npe/100483>\
**Category:** Ignition\
**Tags:** vision\
**Created:** [January 6, 2025, 3:54pm UTC](https://forum.inductiveautomation.com/t/client-tag-expression-with-hasrole-npe/100483 "2025-01-06T15:54:45Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![bschroeder](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bschroeder/32/13260_2.png) [@bschroeder](https://forum.inductiveautomation.com/u/bschroeder)\
**Post date:** [January 6, 2025, 3:54pm UTC](https://forum.inductiveautomation.com/t/client-tag-expression-with-hasrole-npe/100483/1 "2025-01-06T15:54:45Z")

</div>

I've got a weird issue, and I'm not sure if this is because of my usage or if there is an actual problem going on here.

I want to use a Vision Client tag to generate some bit based on the current user roles. IE if the user has the "Operator" role then we will turn on a client tag so that it can be easily tweaked down the road.

The expression that I'm using is:

```python
hasRole('Operator',{[System]Client/User/Username})

```

The User Source I'm using has a failover to another user source.

The main user source is an Ignition internal, the failover is AD.

When I log in to the designer or project with a known user on the default (non-failover) user source, the expression works as expected.

However, if I log in with a user from the failover user source, I get the following NPE:

> **Error**
>
> ```python
> ERROR com.inductiveautomation.factorypmi.application.sqltags.project.ExpressionTagBinding -- Error executing expression for tag "testing".
> com.inductiveautomation.ignition.common.expressions.ExpressionException: Error retrieving user from gateway.
> at com.inductiveautomation.ignition.client.expressions.ClientFunctionFactory$HasRoleFunctionClient.getRoles(ClientFunctionFactory.java:302)
> at com.inductiveautomation.ignition.client.expressions.ClientFunctionFactory$HasRoleFunctionClient.execute(ClientFunctionFactory.java:272)
> at com.inductiveautomation.ignition.client.expressions.ClientDynamicDispatchFunction.execute(ClientDynamicDispatchFunction.java:43)
> at com.inductiveautomation.ignition.common.expressions.FunctionExpression.execute(FunctionExpression.java:69)
> at com.inductiveautomation.factorypmi.application.sqltags.project.ExpressionTagBinding.childInteractionUpdated(ExpressionTagBinding.java:44)
> at com.inductiveautomation.ignition.common.expressions.TagListener.tagChanged(TagListener.java:58)
> at com.inductiveautomation.factorypmi.application.sqltags.ProjectTagSubscriptionManager.subscribe(ProjectTagSubscriptionManager.java:119)
> at com.inductiveautomation.factorypmi.application.sqltags.system.AbstractClientSystemTagManager.subscribe(AbstractClientSystemTagManager.java:98)
> at com.inductiveautomation.factorypmi.application.sqltags.system.AbstractClientSystemTagManager.subscribe(AbstractClientSystemTagManager.java:106)
> at com.inductiveautomation.ignition.client.sqltags.impl.SubManagerAdapter.subscribeAsync(SubManagerAdapter.java:121)
> at com.inductiveautomation.ignition.client.sqltags.impl.SystemTagManager.lambda$subscribeAsync$16(SystemTagManager.java:310)
> at com.inductiveautomation.ignition.gateway.util.GroupMapCollate.lambda$groupMapIndexed$10(GroupMapCollate.java:89)
> at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
> at java.base/java.util.HashMap$EntrySpliterator.forEachRemaining(Unknown Source)
> at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
> at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
> at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
> at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(Unknown Source)
> at java.base/java.util.stream.ReferencePipeline.toArray(Unknown Source)
> at com.inductiveautomation.ignition.gateway.util.GroupMapCollate.groupMapIndexed(GroupMapCollate.java:98)
> at com.inductiveautomation.ignition.client.sqltags.impl.SystemTagManager.subscribeAsync(SystemTagManager.java:293)
> at com.inductiveautomation.ignition.client.tags.impl.ClientTagManagerImpl.lambda$subscribeAsync$9(ClientTagManagerImpl.java:300)
> at com.inductiveautomation.ignition.gateway.util.GroupMapCollate.lambda$groupMapIndexed$10(GroupMapCollate.java:89)
> at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
> at java.base/java.util.HashMap$EntrySpliterator.forEachRemaining(Unknown Source)
> at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
> at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
> at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
> at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(Unknown Source)
> at java.base/java.util.stream.ReferencePipeline.toArray(Unknown Source)
> at com.inductiveautomation.ignition.gateway.util.GroupMapCollate.groupMapIndexed(GroupMapCollate.java:98)
> at com.inductiveautomation.ignition.client.tags.impl.ClientTagManagerImpl.subscribeAsync(ClientTagManagerImpl.java:288)
> at com.inductiveautomation.ignition.common.tags.model.TagManager.subscribeAsync(TagManager.java:79)
> at com.inductiveautomation.ignition.common.expressions.TagListener.startup(TagListener.java:70)
> at com.inductiveautomation.ignition.common.expressions.BoundTagExpression.startup(BoundTagExpression.java:109)
> at com.inductiveautomation.ignition.common.expressions.AbstractExpression.startup(AbstractExpression.java:61)
> at com.inductiveautomation.ignition.common.expressions.FunctionExpression.startup(FunctionExpression.java:62)
> at com.inductiveautomation.factorypmi.application.sqltags.project.ExpressionTagBinding.startBinding(ExpressionTagBinding.java:32)
> at com.inductiveautomation.factorypmi.application.sqltags.project.ProjectTag.startBindingImpl(ProjectTag.java:202)
> at com.inductiveautomation.factorypmi.application.sqltags.project.ProjectTag.startBinding(ProjectTag.java:189)
> at com.inductiveautomation.factorypmi.application.sqltags.ClientTagFolder.startBinding(ClientTagFolder.java:151)
> at com.inductiveautomation.factorypmi.application.sqltags.ClientTagFolder.startBinding(ClientTagFolder.java:151)
> at com.inductiveautomation.factorypmi.application.sqltags.ClientTagFolder.startBinding(ClientTagFolder.java:151)
> at com.inductiveautomation.factorypmi.application.sqltags.project.ProjectTagManager.startup(ProjectTagManager.java:474)
> at com.inductiveautomation.ignition.client.sqltags.impl.SubManagerAdapter.startup(SubManagerAdapter.java:277)
> at com.inductiveautomation.ignition.client.tags.impl.ClientTagManagerImpl.addClientTagProvider(ClientTagManagerImpl.java:165)
> at com.inductiveautomation.factorypmi.designer.model.VisionDesignerImpl.lambda$new$1(VisionDesignerImpl.java:325)
> at java.desktop/java.beans.PropertyChangeSupport.fire(Unknown Source)
> at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
> at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
> at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
> at com.inductiveautomation.ignition.designer.DesignerContextImpl.fireScriptManagerInitialized(DesignerContextImpl.java:247)
> at com.inductiveautomation.ignition.designer.IgnitionDesigner.loadProject(IgnitionDesigner.java:1035)
> at com.inductiveautomation.ignition.designer.IgnitionDesigner$StartupProjectDialogHandler.lambda$new$2(IgnitionDesigner.java:2058)
> at java.base/java.lang.Thread.run(Unknown Source)
> Caused by: java.lang.NullPointerException: Cannot invoke "com.inductiveautomation.ignition.common.user.User.getRoles()" because "user" is null
> at com.inductiveautomation.ignition.client.expressions.ClientFunctionFactory$HasRoleFunctionClient.getRoles(ClientFunctionFactory.java:298)
> ... 54 common frames omitted
> 10:44:16.045 [Designer-Startup] ERROR com.inductiveautomation.factorypmi.application.sqltags.project.ExpressionTagBinding -- Error executing expression for tag "testing".
> com.inductiveautomation.ignition.common.expressions.ExpressionException: Error retrieving user from gateway.
> at com.inductiveautomation.ignition.client.expressions.ClientFunctionFactory$HasRoleFunctionClient.getRoles(ClientFunctionFactory.java:302)
> at com.inductiveautomation.ignition.client.expressions.ClientFunctionFactory$HasRoleFunctionClient.execute(ClientFunctionFactory.java:272)
> at com.inductiveautomation.ignition.client.expressions.ClientDynamicDispatchFunction.execute(ClientDynamicDispatchFunction.java:43)
> at com.inductiveautomation.ignition.common.expressions.FunctionExpression.execute(FunctionExpression.java:69)
> at com.inductiveautomation.factorypmi.application.sqltags.project.ExpressionTagBinding.childInteractionUpdated(ExpressionTagBinding.java:44)
> at com.inductiveautomation.factorypmi.application.sqltags.project.ExpressionTagBinding.startBinding(ExpressionTagBinding.java:33)
> at com.inductiveautomation.factorypmi.application.sqltags.project.ProjectTag.startBindingImpl(ProjectTag.java:202)
> at com.inductiveautomation.factorypmi.application.sqltags.project.ProjectTag.startBinding(ProjectTag.java:189)
> at com.inductiveautomation.factorypmi.application.sqltags.ClientTagFolder.startBinding(ClientTagFolder.java:151)
> at com.inductiveautomation.factorypmi.application.sqltags.ClientTagFolder.startBinding(ClientTagFolder.java:151)
> at com.inductiveautomation.factorypmi.application.sqltags.ClientTagFolder.startBinding(ClientTagFolder.java:151)
> at com.inductiveautomation.factorypmi.application.sqltags.project.ProjectTagManager.startup(ProjectTagManager.java:474)
> at com.inductiveautomation.ignition.client.sqltags.impl.SubManagerAdapter.startup(SubManagerAdapter.java:277)
> at com.inductiveautomation.ignition.client.tags.impl.ClientTagManagerImpl.addClientTagProvider(ClientTagManagerImpl.java:165)
> at com.inductiveautomation.factorypmi.designer.model.VisionDesignerImpl.lambda$new$1(VisionDesignerImpl.java:325)
> at java.desktop/java.beans.PropertyChangeSupport.fire(Unknown Source)
> at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
> at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
> at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
> at com.inductiveautomation.ignition.designer.DesignerContextImpl.fireScriptManagerInitialized(DesignerContextImpl.java:247)
> at com.inductiveautomation.ignition.designer.IgnitionDesigner.loadProject(IgnitionDesigner.java:1035)
> at com.inductiveautomation.ignition.designer.IgnitionDesigner$StartupProjectDialogHandler.lambda$new$2(IgnitionDesigner.java:2058)
> at java.base/java.lang.Thread.run(Unknown Source)
> Caused by: java.lang.NullPointerException: Cannot invoke "com.inductiveautomation.ignition.common.user.User.getRoles()" because "user" is null
> at com.inductiveautomation.ignition.client.expressions.ClientFunctionFactory$HasRoleFunctionClient.getRoles(ClientFunctionFactory.java:298)
> ... 22 common frames omitted
> 
> ```

If I make the default user source for the project the AD and then login with the same AD user as before, it works as expected. No errors.

So it seems that something is wonky with a fail over user source and how I'm doing the expression.

Any ideas?

It looks like I could also use the [System]Client/User/RolesString tag and do the following expression:

```python
indexOf('Operator',coalesce({[System]Client/User/RolesString},'')) > -1

```

It is just strange that the other expression doesn't work as expected.

---

<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:** [January 6, 2025, 4:27pm UTC](https://forum.inductiveautomation.com/t/client-tag-expression-with-hasrole-npe/100483/2 "2025-01-06T16:27:04Z")

</div>

Does just invoking `hasRole('Operator')` work? The function shouldn't need an explicit username in the client, since you're always logged in as _some_ user in Vision, unlike Perspective where you can be truly unauthenticated.

---

<div class="post-metadata">

**Author:** ![bschroeder](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bschroeder/32/13260_2.png) [@bschroeder](https://forum.inductiveautomation.com/u/bschroeder)\
**Post date:** [January 6, 2025, 4:41pm UTC](https://forum.inductiveautomation.com/t/client-tag-expression-with-hasrole-npe/100483/3 "2025-01-06T16:41:35Z")

</div>

Yes, except when changing users it doesn't update the tag, which I would expect. Hence the reason I'm using the `{[System]Client/User/Username}` tag to trigger an update.

---

<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:** [January 6, 2025, 4:45pm UTC](https://forum.inductiveautomation.com/t/client-tag-expression-with-hasrole-npe/100483/4 "2025-01-06T16:45:40Z")

</div>

Consider including it in a throwaway, like so (with my Integration Toolkit):

```python
asList(
	{[System]Client/User/Username},
	hasRole('Operator')
)[1]

```

Something similar can be done with `if()` and duplicate branches.

---

<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:** [January 6, 2025, 5:00pm UTC](https://forum.inductiveautomation.com/t/client-tag-expression-with-hasrole-npe/100483/5 "2025-01-06T17:00:40Z")

</div>

Another option would be to trick the expression into running at a particular rate with `now`, like `now() && hasRole('Operator')` would work I'm pretty sure, and just automatically poll every 1 second. The 'happy path' for `hasRole` with only one argument doesn't make an unnecessary RPC call so it'll return more or less instantly.

Actually... I think even just `{[System]Client/User/Username} && hasRole('Operator')` should work, or maybe `len({[System]Client/User/Username}) > 0 && hasRole('Operator')`? Somewhat awkward, and it would definitely be better if we weren't throwing the NPE, but that should get you the right result and behave the right way.

---

<div class="post-metadata">

**Author:** ![bschroeder](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bschroeder/32/13260_2.png) [@bschroeder](https://forum.inductiveautomation.com/u/bschroeder)\
**Post date:** [January 6, 2025, 5:54pm UTC](https://forum.inductiveautomation.com/t/client-tag-expression-with-hasrole-npe/100483/6 "2025-01-06T17:54:38Z")

</div>

Thanks for the ideas... I'll bounce them around and see what sticks.
