Hello,
Today I have run into the dreaded RuntimeError: maximum recursion depth exceeded (Java StackOverflowError)
within a project library script. I don’t think this is from a cyclic recursion loop, rather I just have deeply nested object calls. Here’s the stack trace when calling a function from the designer:
Traceback (most recent call last):
File "<input>", line 11, in <module>
File "<module:inventory.fulfillment.order>", line 57, in createNewOrder
File "<module:api.util>", line 27, in wrapper
File "<module:api.xero.invoice>", line 33, in createXeroInvoice
File "<module:api.base>", line 274, in put
File "<module:api.base>", line 264, in _call
File "<module:api.base>", line 121, in _request
File "<module:api.base>", line 110, in _requestOnce
RuntimeError: maximum recursion depth exceeded (Java StackOverflowError)
For a bit more context on the stack trace, we have multiple different REST APIs we need to interface with, so I created a base ApiClient in the api.base
project library script. Then api.<ClientName>.client
will have a singleton class that inherits from the base api class, and api.<ClientName>.<endpoint>
will have functions that use the singleton class to call methods from a specific endpoint.
This has been working great for the past few weeks, but today I guess I finally reached the limit in this createNewOrder
script. Is it ok to just increase the Java Stack Size? Could there be a fundamental flaw in my base script that needs to be refactored?
Basically, I’d appreciate any feedback anyone has on how to debug or solve this.
Thanks!
If you execute this from the gateway scope (e.g. temporary timer script or tag event script) I think you can maybe get a full Java stack trace along with the error… that might help diagnose further.
1 Like
Oh good idea, it looks like there is an infinite recursion somewhere. I’ll dig deeper
com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File "", line 13, in valueChanged File "", line 57, in createNewOrder File "", line 27, in wrapper File "", line 33, in createXeroInvoice File "", line 274, in put File "", line 264, in _call File "", line 121, in _request File "", line 110, in _requestOnce RuntimeError: maximum recursion depth exceeded (Java StackOverflowError)
at org.python.core.Py.RuntimeError(Py.java:155)
at org.python.core.Py.JavaError(Py.java:538)
at org.python.core.Py.JavaError(Py.java:536)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:192)
at org.python.core.PyObject.__call__(PyObject.java:422)
at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237)
at org.python.core.PyMethod.__call__(PyMethod.java:228)
at org.python.core.PyMethod.__call__(PyMethod.java:223)
at org.python.core.PyObject._callextra(PyObject.java:589)
at org.python.pycode._pyx30150._requestOnce$10(:110)
at org.python.pycode._pyx30150.call_function()
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
at org.python.core.PyBaseCode.call(PyBaseCode.java:197)
at org.python.core.PyFunction.__call__(PyFunction.java:485)
at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237)
at org.python.core.PyMethod.__call__(PyMethod.java:228)
at org.python.core.PyMethod.__call__(PyMethod.java:223)
at org.python.core.PyObject._callextra(PyObject.java:589)
at org.python.pycode._pyx30150._request$11(:140)
at org.python.pycode._pyx30150.call_function()
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
at org.python.core.PyBaseCode.call(PyBaseCode.java:197)
at org.python.core.PyFunction.__call__(PyFunction.java:485)
at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237)
at org.python.core.PyMethod.__call__(PyMethod.java:228)
at org.python.core.PyMethod.__call__(PyMethod.java:223)
at org.python.core.PyObject._callextra(PyObject.java:589)
at org.python.pycode._pyx30150._call$27(:264)
at org.python.pycode._pyx30150.call_function()
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
at org.python.core.PyBaseCode.call(PyBaseCode.java:197)
at org.python.core.PyFunction.__call__(PyFunction.java:485)
at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237)
at org.python.core.PyMethod.__call__(PyMethod.java:228)
at org.python.core.PyMethod.__call__(PyMethod.java:223)
at org.python.core.PyObject._callextra(PyObject.java:589)
at org.python.pycode._pyx30150.put$30(:274)
at org.python.pycode._pyx30150.call_function()
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
at org.python.core.PyBaseCode.call(PyBaseCode.java:197)
at org.python.core.PyFunction.__call__(PyFunction.java:485)
at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237)
at org.python.core.PyMethod.__call__(PyMethod.java:228)
at org.python.pycode._pyx30272.createXeroInvoice$1(:33)
at org.python.pycode._pyx30272.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 org.python.core.PyObject._callextra(PyObject.java:589)
at org.python.pycode._pyx30140.wrapper$4(:52)
at org.python.pycode._pyx30140.call_function()
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
at org.python.core.PyBaseCode.call(PyBaseCode.java:141)
at org.python.core.PyFunction.__call__(PyFunction.java:426)
at org.python.pycode._pyx30271.createNewOrder$2(:83)
at org.python.pycode._pyx30271.call_function()
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:150)
at org.python.core.PyFunction.__call__(PyFunction.java:426)
at org.python.pycode._pyx30270.valueChanged$1(:13)
at org.python.pycode._pyx30270.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:847)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:829)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:868)
at com.inductiveautomation.ignition.gateway.tags.scripting.TagScriptManagerImpl$FunctionInvokerImpl.run(TagScriptManagerImpl.java:551)
at com.inductiveautomation.ignition.gateway.tags.scripting.events.AbstractTagScript.invoke(AbstractTagScript.java:34)
at com.inductiveautomation.ignition.gateway.tags.scripting.TagScriptManagerImpl$Task.invoke(TagScriptManagerImpl.java:493)
at com.inductiveautomation.ignition.gateway.tags.scripting.TagScriptManagerImpl$TagScriptDispatcher.run(TagScriptManagerImpl.java:453)
at com.inductiveautomation.ignition.common.execution.impl.BasicExecutionEngine$ThrowableCatchingRunnable.run(BasicExecutionEngine.java:550)
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.ScheduledThreadPoolExecutor$ScheduledFutureTask.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 java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.python.core.PyException: RuntimeError: maximum recursion depth exceeded (Java StackOverflowError)
For what it's worth, I've never heard of someone having to increase their stack size in an Ignition project. Not to say someone out there hasn't done it, and there are potentially legitimate cases to do so, but I've literally never had someone come and tell me that they had to.
1 Like
In fact, I think I’ve only ever seen somebody decrease it to reduce the memory overhead on large systems with thousands of threads… and haven’t seen that for years.