openhab / openhab-js

openHAB JavaScript Library for JavaScript Scripting Automation
https://www.openhab.org/addons/automation/jsscripting/
Eclipse Public License 2.0
38 stars 31 forks source link

Error `java.lang.IllegalArgumentException: Invalid type '{com.oracle.truffle.polyglot.PolyglotMap}' of configuration value!` does not show its location in the .js file #176

Closed dilyanpalauzov closed 1 year ago

dilyanpalauzov commented 1 year ago

When I create a JS rule as in

rules.JSRule({
    triggers: my_array.map(y => triggers.ItemStateChangeTrigger(y)),
    execute: (data) => {
      console.log(data)
   }
))

and the elements of my_array are Items (not strings), openHAB 3.3 logs:

2022-11-24 09:58:11.273 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab/automation/js/zz.js': java.lang.IllegalArgumentException: Invalid type '{com.oracle.truffle.polyglot.PolyglotMap}' of configuration value!

The error disappears once I pass to triggers.ItemStateChangeTrigger() a string.

The error message 2022-11-24 09:58:11.273 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab/automation/js/zz.js': java.lang.IllegalArgumentException: Invalid type '{com.oracle.truffle.polyglot.PolyglotMap}' of configuration value!

is very unclear on the exact problem and its location.

Please extend openhab-js to print in such cases the line and column, where the error occurs, and hint that the problem is wrong type passed to triggers.ItemStateChangeTrigger().

florian-h05 commented 1 year ago

The problem why there is no stack trace in this case, is that the error occurs in the Java layer of openHAB and only the message of the exception is logged.

To solve this, we have two options:

I‘ prefer the second option, as this would help with debugging in all cases of errors during the script loading, regardless where they occur.

@jpg0 WDYT?

dilyanpalauzov commented 1 year ago

triggers.ItemStateChangeTrigger() could be extended to accept an Item object as parameter, in addition to string.

jpg0 commented 1 year ago

@florian-h05 I believe that the policy for the Java layer is that stack traces are not logged, except for unanticipated errors within openHAB, indicating that a core fix is required. @kaikreuzer would be able to confirm this.

florian-h05 commented 1 year ago

Okay, but I am wondering if we could have an exception from this policy here, because the logged message clearly says that it is a script problem (Error during evaluation of script 'file:/etc/openhab/automation/js/zz.js') and the stack trace should show that the root cause of the exception is inside the script file.

If we can't, what would be your proposal to avoid such problems? I've also encountered this when I passed the wrong pramater to the Item history classes methods. Introducing type checks for all our wrapper functions is no solution in my opinion.

florian-h05 commented 1 year ago

I‘ve modified the add-on to print the stack trace, but seems like the stack trace doesn‘t help in this case:

Stack trace ``` 2022-11-27 10:32:43.692 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script: java.lang.IllegalArgumentException: Invalid type '{com.oracle.truffle.polyglot.PolyglotMap}' of configuration value! at org.openhab.core.config.core.ConfigUtil.normalizeType(ConfigUtil.java:190) ~[?:?] at org.openhab.core.config.core.ConfigUtil.normalizeTypes(ConfigUtil.java:165) ~[?:?] at org.openhab.core.config.core.Configuration.(Configuration.java:74) ~[?:?] at org.openhab.core.config.core.Configuration.(Configuration.java:64) ~[?:?] at com.oracle.truffle.host.HostMethodDesc$SingleMethod$MHBase.invokeHandle(HostMethodDesc.java:331) ~[?:?] at com.oracle.truffle.host.GuestToHostCodeCache$1.executeImpl(GuestToHostCodeCache.java:96) ~[?:?] at com.oracle.truffle.host.GuestToHostRootNode.execute(GuestToHostRootNode.java:80) ~[?:?] at com.oracle.truffle.api.impl.DefaultCallTarget.callDirectOrIndirect(DefaultCallTarget.java:85) ~[?:?] at com.oracle.truffle.api.impl.DefaultRuntimeAccessor$DefaultRuntimeSupport.callInlined(DefaultRuntimeAccessor.java:160) ~[?:?] at com.oracle.truffle.host.GuestToHostRootNode.guestToHostCall(GuestToHostRootNode.java:102) ~[?:?] at com.oracle.truffle.host.HostMethodDesc$SingleMethod$MHBase.invokeGuestToHost(HostMethodDesc.java:362) ~[?:?] at com.oracle.truffle.host.HostExecuteNode.doInvoke(HostExecuteNode.java:871) ~[?:?] at com.oracle.truffle.host.HostExecuteNode.doOverloadedCached(HostExecuteNode.java:288) ~[?:?] at com.oracle.truffle.host.HostExecuteNodeGen.executeAndSpecialize(HostExecuteNodeGen.java:240) ~[?:?] at com.oracle.truffle.host.HostExecuteNodeGen.execute(HostExecuteNodeGen.java:96) ~[?:?] at com.oracle.truffle.host.HostObject$Instantiate.doObjectCached(HostObject.java:1370) ~[?:?] at com.oracle.truffle.host.HostObjectGen$InteropLibraryExports$Cached.instantiateAndSpecialize(HostObjectGen.java:1731) ~[?:?] at com.oracle.truffle.host.HostObjectGen$InteropLibraryExports$Cached.instantiate(HostObjectGen.java:1701) ~[?:?] at com.oracle.truffle.api.interop.InteropLibraryGen$CachedDispatch.instantiate(InteropLibraryGen.java:7690) ~[?:?] at com.oracle.truffle.js.nodes.function.JSNewNode.doNewForeignObject(JSNewNode.java:206) ~[?:?] at com.oracle.truffle.js.nodes.function.JSNewNodeGen.executeAndSpecialize(JSNewNodeGen.java:141) ~[?:?] at com.oracle.truffle.js.nodes.function.JSNewNodeGen.execute(JSNewNodeGen.java:85) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode$Invoke1Node.createArguments(JSFunctionCallNode.java:841) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode$InvokeNode.execute(JSFunctionCallNode.java:732) ~[?:?] at com.oracle.truffle.js.nodes.access.PropertyNode.evaluateTarget(PropertyNode.java:185) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode$InvokeNode.executeTarget(JSFunctionCallNode.java:739) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode$InvokeNode.execute(JSFunctionCallNode.java:728) ~[?:?] at com.oracle.truffle.js.nodes.control.ReturnNode$TerminalPositionReturnNode.execute(ReturnNode.java:165) ~[?:?] at com.oracle.truffle.js.nodes.binary.DualNode.execute(DualNode.java:125) ~[?:?] at com.oracle.truffle.js.nodes.control.AbstractBlockNode.executeGeneric(AbstractBlockNode.java:85) ~[?:?] at com.oracle.truffle.js.nodes.control.AbstractBlockNode.executeGeneric(AbstractBlockNode.java:55) ~[?:?] at com.oracle.truffle.api.impl.DefaultBlockNode.executeGeneric(DefaultBlockNode.java:65) ~[?:?] at com.oracle.truffle.js.nodes.control.AbstractBlockNode.execute(AbstractBlockNode.java:75) ~[?:?] at com.oracle.truffle.js.nodes.function.FunctionBodyNode.execute(FunctionBodyNode.java:73) ~[?:?] at com.oracle.truffle.js.nodes.function.FunctionRootNode.executeInRealm(FunctionRootNode.java:143) ~[?:?] at com.oracle.truffle.js.runtime.JavaScriptRealmBoundaryRootNode.execute(JavaScriptRealmBoundaryRootNode.java:92) ~[?:?] at com.oracle.truffle.api.impl.DefaultCallTarget.callDirectOrIndirect(DefaultCallTarget.java:85) ~[?:?] at com.oracle.truffle.api.impl.DefaultDirectCallNode.call(DefaultDirectCallNode.java:59) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode$UnboundJSFunctionCacheNode.executeCall(JSFunctionCallNode.java:1277) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode.executeAndSpecialize(JSFunctionCallNode.java:303) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode.executeCall(JSFunctionCallNode.java:248) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode$CallNode.execute(JSFunctionCallNode.java:529) ~[?:?] at com.oracle.truffle.js.nodes.control.ReturnNode$TerminalPositionReturnNode.execute(ReturnNode.java:165) ~[?:?] at com.oracle.truffle.js.nodes.control.AbstractBlockNode.executeGeneric(AbstractBlockNode.java:85) ~[?:?] at com.oracle.truffle.js.nodes.control.AbstractBlockNode.executeGeneric(AbstractBlockNode.java:55) ~[?:?] at com.oracle.truffle.api.impl.DefaultBlockNode.executeGeneric(DefaultBlockNode.java:65) ~[?:?] at com.oracle.truffle.js.nodes.control.AbstractBlockNode.execute(AbstractBlockNode.java:75) ~[?:?] at com.oracle.truffle.js.nodes.function.FunctionBodyNode.execute(FunctionBodyNode.java:73) ~[?:?] at com.oracle.truffle.js.nodes.function.FunctionRootNode.executeInRealm(FunctionRootNode.java:143) ~[?:?] at com.oracle.truffle.js.runtime.JavaScriptRealmBoundaryRootNode.execute(JavaScriptRealmBoundaryRootNode.java:92) ~[?:?] at com.oracle.truffle.api.impl.DefaultCallTarget.callDirectOrIndirect(DefaultCallTarget.java:85) ~[?:?] at com.oracle.truffle.api.impl.DefaultDirectCallNode.call(DefaultDirectCallNode.java:59) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode$UnboundJSFunctionCacheNode.executeCall(JSFunctionCallNode.java:1277) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode.executeAndSpecialize(JSFunctionCallNode.java:303) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode.executeCall(JSFunctionCallNode.java:248) ~[?:?] at com.oracle.truffle.js.nodes.function.JSFunctionCallNode$InvokeNode.execute(JSFunctionCallNode.java:732) ~[?:?] at com.oracle.truffle.js.nodes.access.JSWriteCurrentFrameSlotNodeGen.execute_generic4(JSWriteCurrentFrameSlotNodeGen.java:162) ~[?:?] at com.oracle.truffle.js.nodes.access.JSWriteCurrentFrameSlotNodeGen.execute(JSWriteCurrentFrameSlotNodeGen.java:85) ~[?:?] at com.oracle.truffle.js.nodes.access.JSWriteCurrentFrameSlotNodeGen.executeVoid(JSWriteCurrentFrameSlotNodeGen.java:316) ~[?:?] at com.oracle.truffle.js.nodes.binary.DualNode.executeVoid(DualNode.java:149) ~[?:?] at com.oracle.truffle.js.nodes.binary.DualNode.execute(DualNode.java:124) ~[?:?] at com.oracle.truffle.js.nodes.binary.DualNode.execute(DualNode.java:125) ~[?:?] at com.oracle.truffle.js.nodes.function.FunctionBodyNode.execute(FunctionBodyNode.java:73) ~[?:?] at com.oracle.truffle.js.nodes.function.FunctionRootNode.executeInRealm(FunctionRootNode.java:143) ~[?:?] at com.oracle.truffle.js.runtime.JavaScriptRealmBoundaryRootNode.execute(JavaScriptRealmBoundaryRootNode.java:92) ~[?:?] at com.oracle.truffle.api.impl.DefaultCallTarget.callDirectOrIndirect(DefaultCallTarget.java:85) ~[?:?] at com.oracle.truffle.api.impl.DefaultDirectCallNode.call(DefaultDirectCallNode.java:59) ~[?:?] at com.oracle.truffle.js.lang.JavaScriptLanguage$ParsedProgramRoot.execute(JavaScriptLanguage.java:240) ~[?:?] at com.oracle.truffle.api.impl.DefaultCallTarget.callDirectOrIndirect(DefaultCallTarget.java:85) ~[?:?] at com.oracle.truffle.api.impl.DefaultCallTarget.call(DefaultCallTarget.java:102) ~[?:?] at com.oracle.truffle.polyglot.PolyglotContextImpl.eval(PolyglotContextImpl.java:1296) ~[?:?] at com.oracle.truffle.polyglot.PolyglotContextDispatch.eval(PolyglotContextDispatch.java:63) ~[?:?] at org.graalvm.polyglot.Context.eval(Context.java:399) ~[?:?] at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458) ~[?:?] at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:426) ~[?:?] at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264) ~[java.scripting:?] at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:54) ~[?:?] at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:69) ~[?:?] at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:54) ~[?:?] at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:69) ~[?:?] at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:58) ~[?:?] at java.util.Optional.ifPresent(Optional.java:183) ~[?:?] at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:55) ~[?:?] at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1177) ~[?:?] at org.openhab.core.automation.internal.RuleEngineImpl.runNow(RuleEngineImpl.java:1031) ~[?:?] at org.openhab.core.automation.internal.RuleEngineImpl.runNow(RuleEngineImpl.java:1049) ~[?:?] at org.openhab.core.automation.rest.internal.RuleResource.runNow(RuleResource.java:327) ~[?:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?] at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?] at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:179) ~[bundleFile:3.4.5] at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) ~[bundleFile:3.4.5] at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:201) ~[bundleFile:3.4.5] at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:104) ~[bundleFile:3.4.5] at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) ~[bundleFile:3.4.5] at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96) ~[bundleFile:3.4.5] at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) ~[bundleFile:3.4.5] at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) ~[bundleFile:3.4.5] at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:265) ~[bundleFile:3.4.5] at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234) ~[bundleFile:3.4.5] at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208) ~[bundleFile:3.4.5] at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160) ~[bundleFile:3.4.5] at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:225) ~[bundleFile:3.4.5] at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:298) ~[bundleFile:3.4.5] at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:217) ~[bundleFile:3.4.5] at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) ~[bundleFile:3.1.0] at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:273) ~[bundleFile:3.4.5] at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:550) ~[bundleFile:9.4.46.v20220331] at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:74) ~[bundleFile:?] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:600) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440) ~[bundleFile:9.4.46.v20220331] at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:294) ~[bundleFile:?] at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:501) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[bundleFile:9.4.46.v20220331] at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:90) ~[bundleFile:?] at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.Server.handle(Server.java:516) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487) ~[bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883) [bundleFile:9.4.46.v20220331] at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034) [bundleFile:9.4.46.v20220331] at java.lang.Thread.run(Thread.java:829) [?:?] ```

I can not find any reference to the script in the stack trace.

So seems like we should add type checks to openhab-js.

dilyanpalauzov commented 1 year ago

Please permit to triggers.ItemStateChangeTrigger() to accept in addition to string also an Item object.

florian-h05 commented 1 year ago

Please permit to triggers.ItemStateChangeTrigger() to accept in addition to string also an Item object.

Whilst I will add that functionality, I am wondering why you haven't just passed the item name to the trigger instead of the Item (supposing that my_array holds the Items):

rules.JSRule({
    triggers: my_array.map(y => triggers.ItemStateChangeTrigger(y.name)),
    execute: (data) => {
      console.log(data)
   }
))
dilyanpalauzov commented 1 year ago

I am wondering why you haven't just passed the item name to the trigger instead of the Item (supposing that my_array holds the Items)

Because I have forgotten that I have to pass strings.