Need help debugging PolyglotException

Can anyone please help me debug a org.graalvm.polyglot.PolyglotException on my system, which is producing about 150 lines of crash dump in my logs which is so opaque that I cannot begin to figure out what may be causing it.

2024-02-17 17:03:26.663 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: Error: Failed to create QuantityType from 1970-01-01T00:16:06Z: java.lang.IllegalArgumentException: Invalid Quantity value: 1970-01-01T00:16:06Z
...
ca. 150 more lines...
...

openhab.log (16.2 KB)

Not an polyglot, nor an expert but you use quantity for date time which is reflected by DateTimeType type in OH. While both have a string constructor date do not ship unit which results in error you see.

@splatch yup that much is self evident. The log shows entries concerning “rendering” and “jetty server” so it could be a UI issue. I am thinking that UI (either main UI or Sitemap) is wrongly trying to cast a DateTime item to a QuantityType. My question is where and why and which item?

Ok, polyglot is only going to come from a rule, a done that users JS Scripting or Blockly. So that can narrow things down somewhat.

In this rule, you are using Quantity which should narrow things down a bit more.

The specific wire is as @splatch indicates. You have a rule somewhere that is trying to use the state from a DateTime Item as if it were a Quantity, which isn’t going to work. perhaps somewhere you have an Item that you think is a Number:Time but it’s in reality a DateTime?

There likely isn’t too many rules you have dealing with DateTime items or Number:Time Items.

One thing you can do is edit log4j2.xml to enjoyable the rule events to be loved to events.log. You can correlate the rule running/idle events with the error in openHAB.log to identify the rule the error is giving from.

Stacktrace might tell you over which interface command arrived. The jetty in stacktrace suggests that it is related to http. However, you might have a jetty server receiving request or jetty client embedded in a binding generating such request.
Stacktrace is relevant cause same section of code can be called from several places. Without it we know what fails and (more or less) why, but we can’t tell who/which other code made failed attempt.

The stack trace was attached to my OP

Umm. Not true. It also comes from JavaScript transforms. See below…

Indeed. The problem arises in a specific Text field in a Sitemap (my full sitemap is 1100 lines long so you can imagine how long it took to find that one line). The sitemap text field is linked to an Item that is linked to the SystemInfo binding’s ‘CPU Uptime’ channel. The Item is a Number:Time Item which uses a JavaScript transform to apply a custom state representation so that it will be displayed in ‘11d, 22h, 33m’ format in the UI’s (see below).

image

As you can see from the screenshots above, the transform works fine when the Item is displayed in Main UI. But it fails in the Sitemap UI, and that causes the Polyglot exception and crash dump that I originally reported.

Personally I am rather perplexed about why the JS transform works Ok when displaying in Main UI, yet crashes in Sitemap UI. It strikes me to be a bug in OH core (albeit admittedly a rather seldom edge case). => WDYT?

// item definition
Number:Time System_CPU_Uptime "System CPU Uptime [JS(24g-uptime.js):%s]" <time> {channel="systeminfo:computer:g24:cpu#uptime"}

// JavaScript transform file
(function(minsStr) {
    if (minsStr == "NULL" || minsStr == "UNDEF") return minsStr;
    var mins = Quantity(minsStr).toUnit("min").int;
    var days = Math.floor(mins / (24 * 60));
    mins = mins % (24 * 60);
    var hours = Math.floor(mins / 60);
    mins = Math.floor(mins % 60);
    return days + "d, " + hours + "h, " +  mins + "m";
})(input)

// sitemap
Frame label="System Information" {
    Text item=System_CPU_Uptime
..
}

EDIT: I think the issue is that when Main UI renders the item, the item is (correctly) being passed to the renderer and thus to the the transform as a QuantityType. Whereas when Sitemap UI renders the item, the item is wrongly being passed to the renderer and thus to the the transform as a String. i.e. there is some funny type casting going on in openhab-core or openhab-webui…


EDIT 2: yup :slight_smile:


EDIT 3: or to be more specific, by adding logging to the JS transform, I can see that when the Main UI page is refreshed it receives a QuantityType string “81612 s” whereas when the Basic UI page is refreshed it receives a DateTimeType string “1970-01-01T22:40:12Z” …

// string passed into transform when Main UI page is refreshed
2024-02-18 15:27:14.453 [ERROR] [woof-dog] - 81612 s

// string passed into transform when Sitemap UI page is refreshed
2024-02-18 15:27:39.694 [ERROR] [woof-dog] - 1970-01-01T22:40:12Z

In case anyone is interested, my work around “solution” is to handle both types of string in the JS transform as follows. It is not really a proper solution because IMHO OH should NOT pass different strings into the transform depending on which UI page is being refreshed.

(function(timeStr) {
    if (timeStr == "NULL" || timeStr == "UNDEF") return timeStr;
    var mins = 0;
    try {
        mins = Quantity(timeStr).toUnit("min").int;
    } catch(err) {
        mins = java.time.ZonedDateTime.parse(timeStr).toEpochSecond() / 60;
    }
    var days = Math.floor(mins / (24 * 60));
    mins = mins % (24 * 60);
    var hours = Math.floor(mins / 60);
    mins = Math.floor(mins % 60);
    return days + "d, " + hours + "h, " +  mins + "m";
})(input)

True, I wasn’t considering the Script transform. It’s going to come from JS Scripting is a better way to put it. For now JS Scripting is the only thing in OH that uses GraalVM.

While I was reading this thread, I just wanted to ask whether you use JS transformations … but you luckily found out yourself.

JS transformations are powered by JS Scripting instead of NashornJS since openHAB 4.0, which allows to use everything that the helper library provides.

Unfortunately I don‘t think there is a way for JS Scripting to know whether it is used from a script/rule or transformation, so I think we cannot really improve the logging.

In the UI a Script Action/Condition will have a ruleUID variable. Though I think I learned that is not the case for file based but there is a filename variable. I wonder if one could add the filename to the error log in cases where filename exists, ruleUID in places where it exists, and in cases where neither exist mention it might be from a transform? Maybe I’m missing a case where neither would be defined but it wouldn’t be a transform?

Great idea, there we go: [jsscripting] Improve logging on JS error by florian-h05 · Pull Request #16445 · openhab/openhab-addons · GitHub

1 Like