When to increase Java stack size vs refactor project library?

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.