Could not initialize class com.ibm.icu.util.TimeZone in Blockly Rules that used to work

Running OH 4.1.1-1 Release on a Pi4B

runtimeInfo:
  version: 4.1.1
  buildString: Release Build
locale: en-US
systemInfo:
  configFolder: /etc/openhab
  userdataFolder: /var/lib/openhab
  logFolder: /var/log/openhab
  javaVersion: 17.0.9
  javaVendor: Raspbian
  osName: Linux
  osVersion: 6.1.21-v8+
  osArchitecture: arm
  availableProcessors: 4
  freeMemory: 113098112
  totalMemory: 778567680
  uptime: 47521
  startLevel: 70
addons:
  - automation-jsscripting
  - automation-jsscriptingnashorn
  - binding-androidtv
  - binding-astro
  - binding-denonmarantz
  - binding-exec
  - binding-generacmobilelink
  - binding-gpstracker
  - binding-icalendar
  - binding-icloud
  - binding-ipcamera
  - binding-irobot
  - binding-logreader
  - binding-mail
  - binding-mqtt
  - binding-network
  - binding-networkupstools
  - binding-ntp
  - binding-openweathermap
  - binding-remoteopenhab
  - binding-roku
  - binding-tplinksmarthome
  - binding-zwave
  - misc-homekit
  - misc-openhabcloud
  - persistence-rrd4j
  - transformation-jinja
  - transformation-jsonpath
  - transformation-map
  - transformation-regex
  - ui-basic
  - ui-habpanel
clientInfo:
  device:
    ios: false
    android: false
    androidChrome: false
    desktop: true
    iphone: false
    ipod: false
    ipad: false
    edge: false
    ie: false
    firefox: false
    macos: false
    windows: true
    cordova: false
    phonegap: false
    electron: false
    nwjs: false
    webView: false
    webview: false
    standalone: false
    os: windows
    pixelRatio: 1.5
    prefersColorScheme: light
  isSecureContext: false
  locationbarVisible: true
  menubarVisible: true
  navigator:
    cookieEnabled: true
    deviceMemory: N/A
    hardwareConcurrency: 8
    language: en-US
    languages:
      - en-US
      - en
    onLine: true
    platform: Win32
  screen:
    width: 1707
    height: 1067
    colorDepth: 24
  support:
    touch: false
    pointerEvents: true
    observer: true
    passiveListener: true
    gestures: false
    intersectionObserver: true
  themeOptions:
    dark: light
    filled: true
    pageTransitionAnimation: default
    bars: filled
    homeNavbar: default
    homeBackground: default
    expandableCardAnimation: default
  userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
    like Gecko) Chrome/122.0.0.0 Safari/537.36
timestamp: 2024-03-18T13:59:07.062Z

I’m not sure when it started, but I have some rules that used to work that are now throwing this error

2024-03-18 08:51:09.567 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: java.lang.NoClassDefFoundError: Could not initialize class com.ibm.icu.util.TimeZone
        at com.oracle.truffle.js.runtime.util.IntlUtil.getICUTimeZone(IntlUtil.java:684) ~[?:?]
        at com.oracle.truffle.js.runtime.util.IntlUtil.getICUTimeZone(IntlUtil.java:689) ~[?:?]
        at com.oracle.truffle.js.runtime.JSRealm.getICUTimeZoneFromEnv(JSRealm.java:2430) ~[?:?]
        at com.oracle.truffle.js.runtime.JSRealm.getLocalTimeZone(JSRealm.java:2423) ~[?:?]
        at com.oracle.truffle.js.runtime.builtins.JSDate.localTZA(JSDate.java:393) ~[?:?]
        at com.oracle.truffle.js.runtime.builtins.JSDate.localTime(JSDate.java:385) ~[?:?]
        at com.oracle.truffle.js.builtins.DatePrototypeBuiltins$JSDateGetTimezoneOffsetNode.getTimezoneOffset(DatePrototypeBuiltins.java:846) ~[?:?]
        at com.oracle.truffle.js.builtins.DatePrototypeBuiltinsFactory$JSDateGetTimezoneOffsetNodeGen.execute(DatePrototypeBuiltinsFactory.java:1774) ~[?:?]
        at com.oracle.truffle.js.nodes.function.FunctionRootNode.executeInRealm(FunctionRootNode.java:143) ~[?:?]
        at com.oracle.truffle.js.runtime.JavaScriptRealmBoundaryRootNode.execute(JavaScriptRealmBoundaryRootNode.java:92) ~[?:?]
        at <js>.value(@openhab-globals.js:2) ~[?:?]
        at <js>.value(@openhab-globals.js:2) ~[?:?]
        at <js>.value(@openhab-globals.js:2) ~[?:?]
        at <js>.value(@openhab-globals.js:2) ~[?:?]
        at <js>.javaZDTToJsZDTWithDefaultZoneSystem(@openhab-globals.js:2) ~[?:?]
        at <js>.N(@openhab-globals.js:2) ~[?:?]
        at <js>._(@openhab-globals.js:2) ~[?:?]
        at <js>.:program(<eval>:56) ~[?:?]
        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:262) ~[java.scripting:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
        at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:71) ~[?:?]
        at java.util.Optional.ifPresent(Optional.java:178) [?:?]
        at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:68) [bundleFile:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1188) [bundleFile:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.runRule(RuleEngineImpl.java:997) [bundleFile:?]
        at org.openhab.core.automation.internal.TriggerHandlerCallbackImpl$TriggerData.run(TriggerHandlerCallbackImpl.java:87) [bundleFile:?]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
        at java.lang.Thread.run(Thread.java:840) [?:?]
2024-03-18 08:51:09.583 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'MostRecentiCloudDeviceLocationFromEitherSource' failed: org.graalvm.polyglot.PolyglotException: java.lang.NoClassDefFoundError: Could not initialize class com.ibm.icu.util.TimeZone

I take it the system is unhappy with how I am providing it with Datetime information.

It used to work using the “get date time from item” block. I’ve tried switching to the “date time” block, but still get the error.

Here is the script generated from Blockly:

var Location2, User, Device, Data_Type, Triggering_Item_Name_Components, SourceLocation, DeviceUser, DeviceType, SpringLLU, LatestSource, MidwayLLU, Suffix;

// Describe this function...
function CreateItemName(Location2, User, Device, Data_Type) {
  return [Location2,User,Device,Data_Type].join('');
}

// graalVM
function zdtCompare(zdt1, zdt2, compareOp, precision, compDate) {
  switch (precision) {
    case 'years':
     zdt2 = zdt2.withMonth(zdt1.monthValue());
    case 'months':
     zdt2 = zdt2.withDayOfMonth(zdt1.dayOfMonth());
    case 'days':
     zdt2 = zdt2.withHour(zdt1.hour());
    case 'hours':
     zdt2 = zdt2.withMinute(zdt1.minute());
    case 'minutes':
     zdt2 = zdt2.withSecond(zdt1.second());
    case 'seconds':
     zdt2 = zdt2.withNano(zdt1.nano());
  }
  if (compDate === 'date') {
    zdt1 = zdt1.toLocalDate();
    zdt2 = zdt2.toLocalDate();
  } else if (compDate === 'time') {
    zdt1 = zdt1.toLocalTime();
    zdt2 = zdt2.toLocalTime();
  }
  switch (compareOp) {
    case 'before':
      return zdt1.isBefore(zdt2);
    case 'equal':
      return zdt1.equals(zdt2);
    case 'after':
      return zdt1.isAfter(zdt2);
    case 'beforeEqual':
      return zdt1.isBefore(zdt2) || zdt1.equals(zdt2);
    case 'afterEqual':
      return zdt1.isAfter(zdt2) || zdt1.equals(zdt2);
  }
}


console.info(([ctx.ruleUID,': ',event.itemName].join('')));
Triggering_Item_Name_Components = String(event.itemName).split('_');
SourceLocation = Triggering_Item_Name_Components[0];
SourceLocation += '_';
DeviceUser = Triggering_Item_Name_Components[1];
DeviceUser += '_';
DeviceType = Triggering_Item_Name_Components[2];
DeviceType += '_';
console.info((['Rule: ',ctx.ruleUID,': ',SourceLocation,DeviceUser,DeviceType,CreateItemName('Spring_', DeviceUser, DeviceType, 'Last_Location_Update'),time.toZDT((String(items.getItem((CreateItemName('Midway_', DeviceUser, DeviceType, 'Last_Location_Update')))))),''].join('')));
if (items.getItem((CreateItemName('Midway_', DeviceUser, DeviceType, 'Location'))).state != 'UNDEF' && items.getItem((CreateItemName('Spring_', DeviceUser, DeviceType, 'Location'))).state != 'UNDEF') {
  SpringLLU = (time.toZDT(items.getItem((CreateItemName('Midway_', DeviceUser, DeviceType, 'Last_Location_Update')))));
  MidwayLLU = (time.toZDT(items.getItem((CreateItemName('Spring_', DeviceUser, DeviceType, 'Last_Location_Update')))));
  console.info(([SpringLLU,' : ',MidwayLLU].join('')));
  if (items.getItem((CreateItemName('Spring_', DeviceUser, DeviceType, 'Last_Location_Update'))).state != 'NULL') {
    if (zdtCompare((time.toZDT(items.getItem((CreateItemName('Spring_', DeviceUser, DeviceType, 'Last_Location_Update'))))), (time.toZDT(items.getItem((CreateItemName('Midway_', DeviceUser, DeviceType, 'Last_Location_Update'))))), 'afterEqual', 'nanos', 'dateandtime')) {
      LatestSource = 'Spring_';
    } else {
      LatestSource = 'Midway_';
    }
  } else {
    LatestSource = 'Midway_';
  }
} else if (items.getItem((CreateItemName('Midway_', DeviceUser, DeviceType, 'Location'))).state == 'UNDEF' && items.getItem((CreateItemName('Spring_', DeviceUser, DeviceType, 'Location'))).state == 'UNDEF') {
  LatestSource = String(SourceLocation) + '_';
} else if (items.getItem((CreateItemName('Midway_', DeviceUser, DeviceType, 'Location'))).state == 'UNDEF') {
  LatestSource = 'Spring_';
} else {
  LatestSource = 'Midway_';
}
console.info(([ctx.ruleUID,' latest source location is: ',LatestSource].join('')));
var Suffix_list = ['Location', 'Accuracy', 'Last_Location_Update'];
for (var Suffix_index in Suffix_list) {
  Suffix = Suffix_list[Suffix_index];
  items.getItem((CreateItemName('Most_Recent_', DeviceUser, DeviceType, Suffix))).postUpdate(items.getItem((CreateItemName(LatestSource, DeviceUser, DeviceType, Suffix))).state);
}
items.getItem((CreateItemName('Most_Recent_', DeviceUser, DeviceType, 'Source'))).postUpdate((LatestSource.slice(0, LatestSource.length - 0)));

Here is the Blocky image:

The rule is triggered whenever an iCloud device location changes. The item names are built from the user (me, my wife or my daughter) and device (iPhone or Watch). There is also a Location component. I have two openHAB installations that are 1500 miles apart, and the iCloud binding runs on each of them, and using the remote binding via Tailscale, the iCloud information is shared. This results in more frequent updates than the 5 minute minimum for iCloud, and a back up if iCloud fails on one system but not the other. (For some reason, it seems to be more stable on one than on the other). The function defined at the beginning builds the item name from information in the item that triggered the rule. The rule selects the most recent information to use.

Any suggestions? Thanks.

What type of Item is this, a DateTime Item or a String Item that has a date time formatted String?

Have you ever installed the openhab npm module manually? Do you see $OH_CONF/automation/js/node_modules/openhab or $OH_CONF/automation/js/node_modules/js-joda folders?

The items are datetime. Here is the code for one of them from the UI code window:

label: Last Location Update (Spring)
type: DateTime
category: ""
groupNames:
  - GeorgesAppleWatchAppleWatchSeries7GPSCellular
tags:
  - Point

I’m not sure what that is, so probably not. (I asked the Internet, but that didn’t help).

No, the node_modules folder appears to be empty

openhabian@openhabian-spring4:/etc/openhab/automation/js/node_modules $ ls -a
.  ..

There’s an option to do so from openhabian-config.

That confirms that it’s not installed.

I’ve never seen anything like this error before. The only think I can think of is to force a reinstall of the add-on by clearing the cache. I believe there’s an option in openhabian-config and I know there’s an option to openhab-cli to do this for you. openhab-cli help should show you the option you need.

In a pinch you can do it by hand by stopping OH and delete the contents of /var/lib/openhab/cache and /var/lib/openhab/tmp.

Thanks for the suggestions.

I stopped openHAB with systemctl stop openhab, cleared the cache with sudo openhab-cli clean-cache, and restarted openHAB with systemctl start openhab.

The rule still isn’t working, but the error message is different. It seems like the “get date time from item” block is unhappy with the item data that it is receiving:

2024-03-18 17:18:27.151 [INFO ] [iCloudDeviceLocationFromEitherSource] - MostRecentiCloudDeviceLocationFromEitherSource: Spring_GMH_Watch_Location
2024-03-18 17:18:27.165 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: Error: Failed to parse string Midway_GMH_Watch_Last_Location_Update (Type=DateTimeItem, State=2024-03-18T16:14:48.984-0600, Label=G Watch Last Location Update (Update), Category=, Tags=[Point], Groups=[RemoteopenHABServerMidway]): DateTimeParseException: Text cannot be parsed to a Duration: Midway_GMH_Watch_Last_Location_Update (Type=DateTimeItem, State=2024-03-18T16:14:48.984-0600, Label=G Watch Last Location Update (Update), Category=, Tags=[Point], Groups=[RemoteopenHABServerMidway]), at index: 0
        at <js>.L(@openhab-globals.js:2) ~[?:?]
        at <js>._(@openhab-globals.js:2) ~[?:?]
        at <js>.:program(<eval>:54) ~[?:?]
        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:262) ~[java.scripting:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
        at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:71) ~[?:?]
        at java.util.Optional.ifPresent(Optional.java:178) [?:?]
        at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:68) [bundleFile:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1188) [bundleFile:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.runRule(RuleEngineImpl.java:997) [bundleFile:?]
        at org.openhab.core.automation.internal.TriggerHandlerCallbackImpl$TriggerData.run(TriggerHandlerCallbackImpl.java:87) [bundleFile:?]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
        at java.lang.Thread.run(Thread.java:840) [?:?]
2024-03-18 17:18:27.172 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'MostRecentiCloudDeviceLocationFromEitherSource' failed: org.graalvm.polyglot.PolyglotException: Error: Failed to parse string Midway_GMH_Watch_Last_Location_Update (Type=DateTimeItem, State=2024-03-18T16:14:48.984-0600, Label=G Watch Last Location Update (Update), Category=, Tags=[Point], Groups=[RemoteopenHABServerMidway]): DateTimeParseException: Text cannot be parsed to a Duration: Midway_GMH_Watch_Last_Location_Update (Type=DateTimeItem, State=2024-03-18T16:14:48.984-0600, Label=G Watch Last Location Update (Update), Category=, Tags=[Point], Groups=[RemoteopenHABServerMidway]), at index: 0
2024-03-18 17:19:01.598 [WARN ] [ore.internal.scheduler.SchedulerImpl] - Scheduled job '<unknown>' failed and stopped
java.lang.IllegalStateException: Multi threaded access requested by thread Thread[OH-scheduler-19,5,main] but is not allowed for language(s) js.
        at com.oracle.truffle.polyglot.PolyglotEngineException.illegalState(PolyglotEngineException.java:129) ~[bundleFile:?]
        at com.oracle.truffle.polyglot.PolyglotContextImpl.throwDeniedThreadAccess(PolyglotContextImpl.java:1034) ~[bundleFile:?]
        at com.oracle.truffle.polyglot.PolyglotContextImpl.checkAllThreadAccesses(PolyglotContextImpl.java:893) ~[bundleFile:?]
        at com.oracle.truffle.polyglot.PolyglotContextImpl.enterThreadChanged(PolyglotContextImpl.java:723) ~[bundleFile:?]
        at com.oracle.truffle.polyglot.PolyglotEngineImpl.enterCached(PolyglotEngineImpl.java:1991) ~[bundleFile:?]
        at com.oracle.truffle.polyglot.HostToGuestRootNode.execute(HostToGuestRootNode.java:110) ~[bundleFile:?]
        at com.oracle.truffle.api.impl.DefaultCallTarget.callDirectOrIndirect(DefaultCallTarget.java:85) ~[bundleFile:?]
        at com.oracle.truffle.api.impl.DefaultCallTarget.call(DefaultCallTarget.java:102) ~[bundleFile:?]
        at com.oracle.truffle.polyglot.PolyglotFunctionProxyHandler.invoke(PolyglotFunctionProxyHandler.java:154) ~[bundleFile:?]
        at jdk.proxy19.$Proxy3352.apply(Unknown Source) ~[?:?]
        at org.openhab.core.automation.module.script.internal.action.ScriptExecutionImpl.lambda$1(ScriptExecutionImpl.java:62) ~[?:?]
        at org.openhab.core.internal.scheduler.SchedulerImpl.lambda$12(SchedulerImpl.java:189) ~[?:?]
        at org.openhab.core.internal.scheduler.SchedulerImpl.lambda$1(SchedulerImpl.java:88) ~[?:?]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
        at java.lang.Thread.run(Thread.java:840) [?:?]
Caused by: com.oracle.truffle.api.TruffleStackTrace$LazyStackTrace

There was a bug a little while back where time.toZDT was failing to convert an Item but that was fixed before 4.1.1 I think. This is all very odd. It’s doubly odd that the error changed.

But the work around for the old bug was to use the Item’s state instead of the Item itself. Where you are currently using the “datetime from item” replace that with “datetime: string” block.

image

And pass to that the result of the “get state of Item” block. The state of the Item is a string and time.toZDT() can parse that.

But this is all still really weird.

Thanks.

This worked

I agree that it is weird. With the advantage of your suggestion, I believe this (or something like this) is how I did it before the “datetime from item” block was fixed and I simplified my blockly with it.

I was going to try a clean new set up, but ran into a problem where my backup file is to big for the root disk to restore and haven’t had time to troubleshoot that. When I do, I will see if a clean system makes the problem go away.