openHAB 5.0 Release Discussion

After update from 5.0.0 to 5.0.1 my charts in my classic ui are all emty. No error in the logs. An idea?

Thanks all.

Classic UI does not exist anymore since OH 3 I believe.

Main UI or Basic UI?

Sorry, I meant Basic UI.

And after several tries I find some error logs:

2025-08-25 08:50:59.972 [WARN ] [org.eclipse.jetty.server.HttpChannel] - /chart
java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager
        at sun.font.PlatformFontInfo.createFontManager(PlatformFontInfo.java:37) ~[?:?]
        at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:51) ~[?:?]
        at java.awt.Font.getFont2D(Font.java:526) ~[?:?]
        at java.awt.Font.defaultLineMetrics(Font.java:2394) ~[?:?]
        at java.awt.Font.getLineMetrics(Font.java:2501) ~[?:?]
        at java.awt.font.TextLayout.fastInit(TextLayout.java:597) ~[?:?]
        at java.awt.font.TextLayout.<init>(TextLayout.java:392) ~[?:?]
        at org.knowm.xchart.internal.chartpart.Axis.getXAxisHeightHint(Axis.java:318) ~[?:?]
        at org.knowm.xchart.internal.chartpart.Axis.preparePaint(Axis.java:161) ~[?:?]
        at org.knowm.xchart.internal.chartpart.AxisPair.paint(AxisPair.java:120) ~[?:?]
        at org.knowm.xchart.XYChart.paint(XYChart.java:416) ~[?:?]
        at org.openhab.core.ui.internal.chart.defaultchartprovider.DefaultChartProvider.createChart(DefaultChartProvider.java:305) ~[?:?]
        at org.openhab.core.ui.internal.chart.ChartServlet.doGet(ChartServlet.java:307) ~[?:?]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:497) ~[bundleFile:4.0.4]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:584) ~[bundleFile:4.0.4]
        at org.ops4j.pax.web.service.spi.servlet.OsgiInitializedServlet.service(OsgiInitializedServlet.java:102) ~[?:?]
        at org.eclipse.jetty.servlet.ServletHolder$NotAsync.service(ServletHolder.java:1450) ~[?:?]
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799) ~[?:?]
        at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1656) ~[?:?]
        at org.ops4j.pax.web.service.spi.servlet.OsgiFilterChain.doFilter(OsgiFilterChain.java:113) ~[?:?]
        at org.ops4j.pax.web.service.jetty.internal.PaxWebServletHandler.doHandle(PaxWebServletHandler.java:334) ~[?:?]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) ~[?:?]
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:600) ~[?:?]
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[?:?]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) ~[?:?]
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624) ~[?:?]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) ~[?:?]
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440) ~[?:?]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) ~[?:?]
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505) ~[?:?]
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594) ~[?:?]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) ~[?:?]
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355) ~[?:?]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[?:?]
        at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:234) ~[?:?]
        at org.ops4j.pax.web.service.jetty.internal.PrioritizedHandlerCollection.handle(PrioritizedHandlerCollection.java:96) ~[?:?]
        at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:731) ~[?:?]
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[?:?]
        at org.eclipse.jetty.server.Server.handle(Server.java:516) ~[?:?]
        at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487) ~[?:?]
        at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732) ~[?:?]
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479) ~[?:?]
        at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:439) ~[?:?]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338) ~[bundleFile:9.4.57.v20241219]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315) ~[bundleFile:9.4.57.v20241219]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173) ~[bundleFile:9.4.57.v20241219]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:137) ~[bundleFile:9.4.57.v20241219]
        at org.eclipse.jetty.http2.HTTP2Connection.produce(HTTP2Connection.java:193) ~[?:?]
        at org.eclipse.jetty.http2.HTTP2Connection.onFillable(HTTP2Connection.java:148) ~[?:?]
        at org.eclipse.jetty.http2.HTTP2Connection$FillableCallback.succeeded(HTTP2Connection.java:371) ~[?:?]
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) ~[?:?]
        at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:555) ~[?:?]
        at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:410) ~[?:?]
        at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:164) ~[?:?]
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) ~[?:?]
        at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) ~[?:?]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338) ~[bundleFile:9.4.57.v20241219]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315) ~[bundleFile:9.4.57.v20241219]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173) ~[bundleFile:9.4.57.v20241219]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) ~[bundleFile:9.4.57.v20241219]
        at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409) ~[bundleFile:9.4.57.v20241219]
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883) ~[bundleFile:9.4.57.v20241219]
        at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034) ~[bundleFile:9.4.57.v20241219]
        at java.lang.Thread.run(Thread.java:1583) [?:?]
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.UnsatisfiedLinkError: /usr/lib/jvm/java-21-openjdk-amd64/lib/libfontmanager.so: libharfbuzz.so.0: cannot open shared object file: No such file or directory [in thread "qtp787548883-2429"]
        at jdk.internal.loader.NativeLibraries.load(Native Method) ~[?:?]
        at jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:331) ~[?:?]
        at jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:197) ~[?:?]
        at jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:139) ~[?:?]
        at jdk.internal.loader.NativeLibraries.findFromPaths(NativeLibraries.java:259) ~[?:?]
        at jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:249) ~[?:?]
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:2427) ~[?:?]
        at java.lang.Runtime.loadLibrary0(Runtime.java:916) ~[?:?]
        at java.lang.System.loadLibrary(System.java:2063) ~[?:?]
        at sun.font.FontManagerNativeLibrary$1.run(FontManagerNativeLibrary.java:60) ~[?:?]
        at java.security.AccessController.doPrivileged(AccessController.java:319) ~[?:?]
        at sun.font.FontManagerNativeLibrary.<clinit>(FontManagerNativeLibrary.java:33) ~[?:?]
        at sun.font.SunFontManager$1.run(SunFontManager.java:269) ~[?:?]
        at sun.font.SunFontManager$1.run(SunFontManager.java:267) ~[?:?]
        at java.security.AccessController.doPrivileged(AccessController.java:319) ~[?:?]
        at sun.font.SunFontManager.initStatic(SunFontManager.java:267) ~[?:?]
        at sun.font.SunFontManager.<clinit>(SunFontManager.java:262) ~[?:?]
        ... 64 more

I run openhab from docker container.

With error message I found the solution in Java / Chart issue with Docker install (OH5.0.1)?

Sorry for double post.

Many thanks to all involved in the new openHAB 5 release. I’ve upgraded my instance from openHAB 4 and mostly everything works fine or could be adjusted easily. One thing is currently still not working: I have in my (textual) rule a global variable to set a generic value for a sleep statement, which is used several times in this rule file. Until the latest openHAB 4 release all was working fine. But since I’ve upgraded to openHAB 5 I’m receiving an error everytime the rule is triggered like

2025-08-25 08:22:11.255 [ERROR] [.handler.AbstractScriptModuleHandler] - Script execution of rule with UID 'system-1' failed: An error occurred during the script execution: Could not invoke method: java.lang.Thread.sleep(java.time.Duration) on instance: null in system

Meanwhile I simplified the rule to and here is the code excerpt showing all relevant parts

var Number delayCommand = 800

rule "Test rule"
when
  Time cron "11 * * ? * * *"
then
  logInfo("Test rule","Before Delay")
  Thread::sleep(delayCommand)
  logInfo("Test rule","After Delay")
end

I can see the entry ā€œBefore Delayā€ in the openhab log-file, but directly afterwards the above error message appears and the ā€œAfter Delayā€ command is not shown in the openhab.log file.

Some information to my Installation:

  • Debian 12 system
  • openHAB 5.0.1-1 installed from official openHAB repo
  • zulu21-jdk (21.0.8-3)

Does anyone has a clue on how to use (correctly) global parameters in rule files starting with openHAB 5?

Thanks,

Jochen

I finally upgraded to 5.0.1 (from 4.3.5).

I now seem unable to make ā€œShow advancedā€ work in thing configuration. In fact, none of the configurations appear:

The ā€œcodeā€ tab also doesn’t show (in any thing):

I’ve cleared the cache (sudo openhab-cli clean-cache), but to no avail… Stopcontact laptop was a newly created thing, and I again deleted it and recreated it. Also no effect.


For in case it’s useful, I’d like to add that I saw these errors during the (apt) upgrade process:

[main] ERROR org.openhab.core.storage.json.internal.JsonStorage - Couldn't deserialize value 'org.openhab.core.storage.json.internal.StorageEntry@4f9a3314'. Root cause is: org.openhab.core.tools.internal.Upgrader$UpgradeRecord
...
[main] ERROR org.openhab.core.storage.json.internal.JsonStorage - Couldn't deserialize value 'org.openhab.core.storage.json.internal.StorageEntry@4f9a3314'. Root cause is: org.openhab.core.tools.internal.Upgrader$UpgradeRecord
...
[main] ERROR org.openhab.core.storage.json.internal.JsonStorage - Couldn't deserialize value 'org.openhab.core.storage.json.internal.StorageEntry@fd07cbb'. Root cause is: org.openhab.core.tools.internal.Upgrader$UpgradeRecord
...
[main] ERROR org.openhab.core.storage.json.internal.JsonStorage - Couldn't deserialize value 'org.openhab.core.storage.json.internal.StorageEntry@fd07cbb'. Root cause is: org.openhab.core.tools.internal.Upgrader$UpgradeRecord

So, this turns out to be another case of:

https://github.com/openhab/openhab-docker/issues/475

I think it means that delayCommand is null. I did some experiment myself, and got the same result when delayCommand is invalid/not defined. When I put a number there instead, it works. Maybe logging delayCommand in ā€œBefore Delayā€ could shed some light.

I’ve also had some trouble with ā€œadvancedā€, it used to show any ā€œadvancedā€ value that wasn’t default (aka changed ones), that seems to no longer be the case, and I think I’ve had to reload to get the ā€œadvancedā€ entries to show up (not sure what exactly solved it, didn’t keep at record when it happened). I’m also seeing the vertical scrollbars mysterically disappear now, where a reload might or might not bring them back.

A reload now made all configuration options visible. Did I try that earlier today…? I can’t recall :grimacing:

This might be something new in Java 21 perhaps? I’ve not heard about this changing at all but something is going on.

The error is saying that sleep() is expecting a java.time.Duration but you are passing it a Number.

But reading the javadocs, it never should have worked with a Number either as sleep() expects a long, not a Number. But maybe the ability to accept a Duration is new in Java 21 and now Rules DSL can no longer properly convert the Number to a long.

What ever the root cause, the fix will either be:

var delayCommand = 800

or

var long delayCommand = 800

or

Thread::sleep(delayCommand.longValue)

Type failures like these are rampant in Rules DSL and it’s the main reason I recommend against it’s use for new rules development.

That’s how Rules DSL reports type errors. If you try to make a function call or do an operation without using the exact type required and Rules DSL can’t figure out how to cast it to the proper type it throws this null error.

It might be the case that the variable is null but given that variable will get populated before any of the rules in that file are even created that is unlikely. I think that Java 21 added Duration as an option to pass to sleep() and now Rules DSL is getting confused because it only ever looks up the type hierarchy, never down. So it sees you’ve passed an Object and one of the sleep() functions now takes an Object. So it marches up the class hierarchy until it gets to Object. It never found a match so it returns null as the result of the type cast.

1 Like

I think there’s something dodgy here, because I think I’ve reloaded several times with no result, then navigated back and forth some, and then ā€œsuddenlyā€ it works. I’m certain that’s the way it is with the scrollbars, but have some vague recollection that it was similar with ā€œadvancedā€.

You are indeed correct that sleep() now also supports Duration, so maybe there is something that could be done in Core to address this? I assume that Number → long is a quite frequent expected result when it comes to sleep().

:+1:

This sounds like a plausible explanation, I haven’t studied the Rules DSL stuff at all, but is there really no way to ā€œremedyā€ things like this? By that I mean: Is this completely outside OH’s control, and lies entirely within the realm of xtend/xtext?

Indeed the fix is to either remove ā€œNumberā€ from the definition of the variable or to replace it by long. Thanks. Was somehow to obvious to be found… :smiley:

I don’t see how. Rules DSL is just using the raw Java classes in this case. Everything involved here is part of Java.

Monkey patching really isn’t a thing in Java so OH can’t really easily just add a function to java.lang.Thread that takes a Number. If anything can be done to address it it will probably have to be upstream in the Xtend project and not really something OH could or should fix just here.

That’s my understanding. These are all core language features. OH would have to reimplement a good part of the core language to change something as fundamental as type inference. And changing something that fundamental is very likely to break the whole language in strange and unexpected ways.

In Rules DSL you must follow these rules of thumb to avoid these sorts of type errors:

  1. Never force the type of a variable unless you are initializing it to null. In all other cases, let Rules DSL figure out the type at runtime based on what you assign to it.
val Number duration = 800 // never do this
val duration = 800 // always do this
var Number duration = null`// always do this
  1. The first argument to an operation sets the type of the operation.
var concat = myNumber + myString // will likely fail with a null error because it will use the + operation from Number and you can't add a String to a Number
var concat = myString + myNumber // will likely succeed and concatenate the toString of myNumber to myString
  1. There will be times when you must convert the type because Rules DSL will simply fail. When you must, do so at the last possible moment. For example, if you have a Number and what you are calling needs a long and Rules DSL can’t figure that out on it’s own, wait until you make the function call to convert to a long by calling longValue.

Rule 1 is especially important because the language actively punishes you when you over specify the types of the variables. If you have even moderately complex math operations in your rule, forcing the types of the variables can add minutes to the amount of time it takes to parse that rule when it’s initially loaded. Furthermore, the type of the variable can change. Take the following code:

var long a = 10
var long b = 2
a = a+b

What type is a after this addition? It should be long but it’s actually BigDecimal. The result of all math operations in Rules DSL is BigDecimal.

You shouldn’t have to know all of this stuff just to make a simple rule. This is why I’m in the anti-Rules DSL. All the other rules languages have caught up to or surpassed any advantages Rules DSL once had to justify it’s use as the default language most should use. It is now incomplete (e.g. can’t access Item metadata), weird, an no longer the simplest to learn and use despite it’s weirdness.

Java is typed, so it actually has little to do with this. Rules DSL ā€œpretends to beā€ untyped, and this is where things fail AFAICT. So, somewhere, a logic that tries to convert untyped (or quasi typed) variabes into some actual Java type resides, and this seems to be where it fails. I mean: returning null if you can’t find the proper type, but still being unable to log the fact that you can’t resolve the type? This looks dodgy to me, wherever it resides.

There is no such thing in Java (or, they introduced some of this in later versions, but I doubt that’s what’s used here). So, the ā€œtype interferenceā€ is done either by OH or by xtend/xtext.

I agree, but I think the ā€œmistakeā€ here is trying to make it untypes. Writing ā€œproperā€ type interference is a huge task, something you should leave to those that ā€œconstruct languagesā€ - and even they often fail, which is why untyped languages really never work properly.

That’s a separate issue I believe. I think that’s because nobody ā€œbothersā€ to update it when things are added in OH. Probably because it’s complex and too few people know how to do it. But, it’s probably not ā€œan inherit problemā€ with Rules DSL.

It’s a core part of Xtend. It’s not done by OH. It’s all Xtend and Java and the interaction between the two, nothing implemented in OH itself.

I frankly don’t care about the root cause. Maybe the language could be improved. I’d love to see it (hasn’t happened in over a decade but who knows) . When that happens I’ll change my stance. Until that happens, the language is unfit for purpose and I will continue to warn against it’s use. The language is what it is now, not what it could become some day.

It looks like you’re right here. Sadly, Xtend seems like yet another one of those ā€œfailed projectsā€ that fizzled out over time. Their presentation page still boasts about Java 8 and generics support. Type interference is built in, documentation is sparse.

I’d say that if the type interference stuff is unfixable/untouchable, I can see why nobody bothers to extend it. It’s a bit like beating a dead horse…

Hello,

After migrating to Openhab 5 (and Java 21 and Debian 13), the android app is very often unresponsive (ā€œsocket closedā€) whereas the web UI is all right.

Looking at my reverse proxy, I see that the web UI makes ā€œ/basicui/ā€ requests that are served instantaneously, whereas the android app makes ā€œ/rest/ā€ requests that seem to timeout.

Can you help me finding where to look now ?

Cheers !

You’re right. It is defined in org.openhab.core.items.Item.json. And yes, I’m surprised…

There’s now a new 5.0.1 Debian Docker image that should fix this error. So try pulling it and then recreate your container.

2 Likes

I built a container with the new image and it seems to be fine. Thanks!

1 Like