# Unable to execute perspective functions on session property change

**URL:** <https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [March 30, 2022, 1:08am UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784 "2022-03-30T01:08:32Z")\
**Posts on this page:** 13\
**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:** [March 30, 2022, 1:08am UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/1 "2022-03-30T01:08:32Z")

</div>

I am trying to execute any kind of perspective function (particularly `system.perspective.openDock`) on a change script for a session custom property and have noticed that I don’t have access to a perspective session in that scope.

On top of that even providing it as a parameter, it won’t allow me to execute it. Is there something I am missing here or am I running into a bug?

The script (on `session.custom.debugging.showDebugContent`, a boolean):

```auto
# What I actually want to run
# if currentValue.value == True:
#	system.perspective.openDock("dockedDiagnostics", sessionId=self.props.id)

# What I did in this example
system.util.getLogger("Session").info(self.props.id)
system.perspective.print("Session", sessionId=self.props.id)

```

The logs when I trigger this script:

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

> **The Traceback**
>
> ```auto
> com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File "", line 5, in valueChanged at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.lambda$operateOnPage$0(AbstractScriptingFunctions.java:64) at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.operateOnSession(AbstractScriptingFunctions.java:120) at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.operateOnPage(AbstractScriptingFunctions.java:47) at com.inductiveautomation.perspective.gateway.script.PerspectiveScriptingFunctions.print(PerspectiveScriptingFunctions.java:514) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: No perspective page attached to this thread.
> 
> at org.python.core.Py.JavaError(Py.java:547)
> 
> at org.python.core.Py.JavaError(Py.java:538)
> 
> at org.python.core.PyReflectedFunction. __call__ (PyReflectedFunction.java:192)
> 
> at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction. __call__ (ScriptManager.java:541)
> 
> at org.python.core.PyObject. __call__ (PyObject.java:400)
> 
> at org.python.pycode._pyx40.valueChanged$1(:5)
> 
> at org.python.pycode._pyx40.call_function()
> 
> at org.python.core.PyTableCode.call(PyTableCode.java:173)
> 
> at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
> 
> at org.python.core.PyFunction.function ___call__ (PyFunction.java:474)
> 
> at org.python.core.PyFunction. __call__ (PyFunction.java:469)
> 
> at org.python.core.PyFunction. __call__ (PyFunction.java:464)
> 
> at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:831)
> 
> at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:813)
> 
> at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:806)
> 
> at com.inductiveautomation.ignition.common.script.ScriptManager$ScriptFunctionImpl.invoke(ScriptManager.java:994)
> 
> at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.invoke(ProjectScriptLifecycle.java:871)
> 
> at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:137)
> 
> at com.inductiveautomation.perspective.gateway.model.PropertyChangeScript.access$001(PropertyChangeScript.java:27)
> 
> at com.inductiveautomation.perspective.gateway.model.PropertyChangeScript$ScriptSequencer.run(PropertyChangeScript.java:153)
> 
> at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
> 
> at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
> 
> at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
> 
> at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
> 
> at com.inductiveautomation.perspective.gateway.threading.BlockingWork$BlockingWorkRunnable.run(BlockingWork.java:42)
> 
> at java.base/java.lang.Thread.run(Unknown Source)
> 
> Caused by: org.python.core.PyException: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: No perspective page attached to this thread.
> ... 26 common frames omitted
> Caused by: java.lang.IllegalArgumentException: No perspective page attached to this thread.
> at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.lambda$operateOnPage$0(AbstractScriptingFunctions.java:64)
> at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.operateOnSession(AbstractScriptingFunctions.java:120)
> at com.inductiveautomation.perspective.gateway.script.AbstractScriptingFunctions.operateOnPage(AbstractScriptingFunctions.java:47)
> at com.inductiveautomation.perspective.gateway.script.PerspectiveScriptingFunctions.print(PerspectiveScriptingFunctions.java:514)
> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
> at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
> at java.base/java.lang.reflect.Method.invoke(Unknown Source)
> at org.python.core.PyReflectedFunction. __call__ (PyReflectedFunction.java:190)
> 
> ... 23 common frames omitted
> 
> ```

EDIT: Note, I did also try this with just a print, no `sessionId` parameter, same error. I figured that since the `self` reference in the script is the session itself, it would have access to itself from any perspective functions.

v.8.1.15 and 8.1.14

---

<div class="post-metadata">

**Author:** ![ryan.white](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ryan.white/32/73193_2.png) [@ryan.white](https://forum.inductiveautomation.com/u/ryan.white)\
**Post date:** [March 30, 2022, 8:18pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/2 "2022-03-30T20:18:16Z")

</div>

The log’s last line appears to be complaining that it doesn’t have any perspective pageId. Both the print and openDock have the pageId as an optional parameter, but it might be required if you are calling it on a session property instead of an actual view.

You run into the same problem with running these functions in a session level message handler, you need to provide a pagId.

See if you can pass the current open page’s pageID upwards to a session variable and pass that to the print or openDock function (maybe a small script that runs on the ‘OnStartup’ event)

---

<div class="post-metadata">

**Author:** ![gdube](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/gdube/32/41701_2.png) [@gdube](https://forum.inductiveautomation.com/u/gdube)\
**Post date:** [March 30, 2022, 8:50pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/3 "2022-03-30T20:50:47Z")

</div>

I don’t know the pageId thing Ryan is talking about, but as an alternative, can’t you add a property on your docked view bound to that session property, and add your change script there?

---

<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:** [March 30, 2022, 9:05pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/4 "2022-03-30T21:05:14Z")

</div>

> [@ryan.white](#):
>
> See if you can pass the current open page’s pageID upwards to a session variable and pass that to the print or openDock function

The issue here is that I need this to work across multiple pages in the same session, that's why I had put this on a session property. I get the comment it says that if you are "targeting a different session" than you need a PageID, that makes sense, but I would feel like the session itself should have the local variables present to make session based calls, since I am not "targeting a different session"

> [@gdube](#):
>
> but as an alternative, can’t you add a property on your docked view bound to that session property, and add your change script there?

I think I could do something like this, but I am not sure how a hidden docked view will handle its changes when there is another docked view in the way

However I still believe that workarounds aside, the session should be able to call session scoped scripts

---

<div class="post-metadata">

**Author:** ![kvane](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kvane/32/22228_2.png) [@kvane](https://forum.inductiveautomation.com/u/kvane)\
**Post date:** [March 30, 2022, 9:06pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/5 "2022-03-30T21:06:19Z")

</div>

I think this thread has the explanation you are looking for:

> [@"No perspective page attached to this thread" when trying to openPopup from Session custom property change](https://forum.inductiveautomation.com/t/no-perspective-page-attached-to-this-thread-when-trying-to-openpopup-from-session-custom-property-change/36978/2):
>
> For Perspective to open a Popup, it needs to know what Page to open the Popup on. In most places within Perspective, the triggers are from components, which by definition are already part of a Page. Session properties are NOT part of a page, and so even though they are part of a session, there is no direction as to which page they should open on. That’s why your call is not working. The warning is telling you that the thread on the Gateway which is executing your script has no context as to whi…

---

<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:** [March 30, 2022, 9:20pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/6 "2022-03-30T21:20:22Z")

</div>

Okay, so looking through that I understand that it requires a pageId,

However I feel like the documentation is a little confusing here. It matches the same structure as the `system.perspective.sendMessage` with a required the optional session and then page, but this time its technically an optional session and page together. Its not super clear from the documentation that if you want to use the sessionId property at all (even for the session you are currently in) that you need to provide a pageId. It reads out more like you can provide session, or you can provide session and target a specific page.

That would make it more clear why you can’t make session based calls from the session object itself

Is it expected to be able to do the perspective specific functions across an entire session? or is it always intended (aside from `sendMessage`) to be session & page based?

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [March 30, 2022, 9:50pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/7 "2022-03-30T21:50:09Z")

</div>

The use of a perspective package function in a session property change script depends on what the function needs in order to execute. If something would act on a page, then it needs to have a pageId. If you had done something like `system.perspective.closeSession()`, well, that doesn’t need to know about what page you want to act on because you’re acting on the session. The `.logout()` function would behave similarly.

When you’re using `system.perspective.sendMessage()` somewhere _within a page_, then you already have implicit access to the properties of the page, and so the function can fall back to using those. The session property change scripts are operating independent of any page and so don’t have the fallback values you seem to be expecting.

---

<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:** [March 30, 2022, 10:47pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/8 "2022-03-30T22:47:02Z")

</div>

> [@cmallonee](#):
>
> The session property change scripts are operating independent of any page and so don’t have the fallback values you seem to be expecting.

Would be a nice feature to allow those functions executed in a session scope to just hit all pages by default, the same way that a page implicitly executes on a page as well.

---

<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:** [March 30, 2022, 10:48pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/9 "2022-03-30T22:48:52Z")

</div>

> [@kgamble](#):
>
> to just hit all pages by default

Ugh. Please, no. Those of us who like to have many tabs open won't appreciate it.

---

<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:** [March 30, 2022, 10:52pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/10 "2022-03-30T22:52:01Z")

</div>

> [@pturmel](#):
>
> Those of us who like to have many tabs open won’t appreciate it.

Please don't tell me you're one of these kinds of people 😉 ...

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

---

<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:** [March 30, 2022, 10:54pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/11 "2022-03-30T22:54:21Z")

</div>

> [@kgamble](#):
>
> Please don’t tell me

Close your ears, then, because yes. (:

But not _all_ the time.

---

<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:** [March 30, 2022, 11:01pm UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/12 "2022-03-30T23:01:38Z")

</div>

> [@pturmel](#):
>
> Close your ears, then, because yes. (:

And to think I looked up to you....

> [@pturmel](#):
>
> Ugh. Please, no. Those of us who like to have many tabs open won’t appreciate it.

In reality though now that I think about it, by default probably isn't the best answer here, however at least adding the ability would be nice. Something like sending a session with no page seems fair, since it doesn't do anything right now on its own

At least updating the documentation to be more clear would be helpful

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [March 31, 2022, 2:32am UTC](https://forum.inductiveautomation.com/t/unable-to-execute-perspective-functions-on-session-property-change/57784/13 "2022-03-31T02:32:54Z")

</div>

We could absolutely not do it by default because it would have a large impact on the way current projects work.
