Problem with graaljs script transformation in .things file

Hi there,

i migrated to 4.0.0.M1 an hour ago.
Did all the “before installation” steps mentioned here and its working so far.
But i cannot get my js transformations to work again with the modbus binding.

My .items file looks like this at the moment:

Thing data LWZ_RaumIstTemperaturHK1             "LWZ404SOL Raum IstTemperatur HK1"          [ readStart="0",  readValueType="int16", readTransform="SCRIPT(graaljs:divide10.script)" ]

I’ll tried different approaches in the readTransform but i still get the following error:

2023-03-12 18:14:59.585 [ERROR] [s.internal.SingleValueTransformation] - transformation throws exception [transformation=SCRIPT(graaljs:divide10.script), response=230]
org.openhab.core.transform.TransformationException: Could not get script for UID 'divide10.script'.

The divide10.script file is there. It looks like this:

(function(data) {
	var DIVIDE_BY = 10;
	return parseFloat(data) / DIVIDE_BY;

What am i missing?
Thanks for your help.

where did you store the script file? Should be in the transform/ folder.

Hi Udo,

yes the file is in the transform/ folder. I renamed it from .js to .script. the folder stays the same.

In a Thing shouldn’t it be the following?


i already tried this. the error is the same:

[ERROR] [s.internal.SingleValueTransformation] - transformation throws exception [transformation=SCRIPT:graaljs:divide10.script, response=188]
org.openhab.core.transform.TransformationException: Could not get script for UID 'divide10.script'.

and to confirm … the file seems to me in the right spot:

Assuming openHAB-conf is the config folder OH is working off of that looks correct. I know others have managed to get the transformation to work. Maybe there is something unique about that binding? Or maybe the file permissions are off and OH can’t read the file?

I use the official modbus binding

The path didn’t changed for years.

Ok my fault. a simple restart did the trick.

The correct syntax is

Thing data LWZ_RaumIstTemperaturHK1             "LWZ404SOL Raum IstTemperatur HK1"          [ readStart="0",  readValueType="int16", readTransform="SCRIPT:graaljs:divide10.script" ]

Thanks for your help. And sorry for bothering :wink:


I opened an issue for this a few days ago. It will be fixed in OH 4. For now, when adding a new transformation file of any type, not just SCRIPT, a restart of OH is required to recognize it.

I’m sorry to say that since OH 4.0.0.M2 i get the annoying error again and all my item values are not transformed anymore. With M1 the graaljs transformations worked. M2 crashed them.
Am I alone with this problem?

s.internal.SingleValueTransformation] - couldn't transform response because transformationService of type 'SCRIPT' is unavailable

If you run the milestone or snapshot versions of OH, you really need to watch the corresponding discussion thread: openHAB 4.0 Milestone discussion - #204 by icompas and the announcements: openHAB 4.0 Milestone Builds - #2 by Kai, and when something breaks be sure to check the latest docs too.

This is true all the time but even more critical when a new major version is in the works where breaking changes are allowed with abandon.

SCRIPT no longer exists. See:

1 Like

If i run into problems I keep searching the community threads and the documentations.
But if I do not find my keywords I often get lost.

I know about the problems one can jump in especially if upgradeing to a new version of OH from posts you did earlier.

I also read through the improvements in the release notes from Kai but failed to spot the one with “transformations” which would have answered my question.

Found the solution now. Maybe it helps others:

First I created the transformations in the new Menu Settings > Transformations (divide10, divide100 …)


I altered my .things file with the following syntax:

Bridge modbus:tcp:stiebel "Bridge Modbus Stiebel LWZ404SOL ISG" [ host="", port=9050, id=2 ] {

//readStart Adresse muss um 1 reduziert werden

  // Block 1: Systemwerte (Ist)
  Bridge poller isg_systemwerte                     "Bridge ISG_Poller_Systemwerte"           [ start=0, length=35, refresh=30000, type="input" ] {
    Thing data LWZ_RaumIstTemperaturHK1             "LWZ404SOL Raum IstTemperatur HK1"          [ readStart="0",  readValueType="int16", readTransform="JS(config:js:divide10)" ]

Everything woks fine now. Nice solution by the way.
Thanks again Rich. I’ll try to get better :wink:

1 Like

My reply wasn’t meant to chide or say you should have done better so much as telling you as you go forward the best way to keep up with these breaking changes.

There really is little way around it. If you run the milestones, you must actually open and review at least each of the runtime PRs because the title doesn’t always tell you what you need to know.

And especially if you run into trouble, the first place they get reported is that milestone discussion thread. If your problem isn’t already discussed there, you need to add a post so the devs see it. They don’t always follow all the forum, particularly replies to a month old thread. By they do tend to watch that thread because that’s where regressions and bugs get reported first usually.

And don’t forget the docs. For the most part, the docs are keeping up with the changes. When something breaks, it’s always a good idea to review the docs to see if there’s a new way to do it or something else changed.

Going to the forum and searching is usually the best thing to try first, except when dealing with milestones or snapshots. These are so new there will be very few threads opened that are relevant and most of the useful info will be in the places I outline above.

This isn’t necessarily common knowledge, particularly since the milestone releases between major versions (e.g. 3.3 M2) tend to be relatively breaking change free. It’s only these milestones before the first release of a new whole version number (i.e. X.0.0 MY, e.g. 2.0.0 M2, 3.0.0 M4, 4.0.0 M2) where there can be lots of breaking changes between milestones. Sometimes, as in this case, a breaking change will be introduced and then reversed or partially reversed. So for these milestones, the typical approach to finding information about solving a problem is different.

Thing data SungrowMPPT2Current "Sungrow MPPT2 Stromstärke" [readStart = "5013", readValueType="int16", readTransform="JS(config:js:divide10)"]

It doesn’t work for me … I used the syntax above @GunMaster reported to work but I’m getting the exception below when trying to migrate. Using yesterday’s snapshot.

Transformation file is there but sounds like it’s looking for some UID not file ?
Also, this imho does not match the docs, the config:js: is not mentioned there.
According to docs it would need to be readTransform="JS(divide10.js)", right ?

Any idea ?
(btw Rich do you have a good (“tight”) log level set to share to debug this ?)

2023-06-28 09:17:57.776 [ERROR] [ing.modbus.internal.SingleValueTransformation] - transformation throws exception [transformation=JS(config:js:divide10), response=10]
org.openhab.core.transform.TransformationException: Could not get script for UID 'config:js:divide10'.
        at org.openhab.core.automation.module.script.ScriptTransformationService.transform( ~[?:?]
        at org.openhab.binding.modbus.internal.SingleValueTransformation.transform( ~[?:?]
        at org.openhab.binding.modbus.internal.CascadedValueTransformationImpl.transform( ~[?:?]
        at org.openhab.binding.modbus.internal.ValueTransformation.transformState( ~[?:?]
admin@mysmarthouse:/etc/openhab/things $ ls -l ../transform/divide10.js
-rw-rw-r-- 1 openhab openhab 306 18. Sep 2020  ../transform/divide10.js
admin@mysmarthouse:/etc/openhab/things $ cat ../transform/divide10.js
// Wrap everything in a function (no global variable pollution)
// variable "input" contains data passed by openHAB
(function(inputData) {
    // on read: the polled number as string
    // on write: openHAB command as string
    var DIVIDE_BY = 10;
    return parseFloat(inputData) / DIVIDE_BY;

I can confirm the syntax mentioned above ist still working for me in Milestone 4.0.0.M3

what’s your filename suffix?


I created the divide transformations in the new UI Option.
This is what i meant with this:



1 Like

It was very very confusing to follow what happened.
Kai said in march JS no longer exists use SCRIPT now Rich says in april SCRIPT no longer exists

ok which is why OH finds it under that UID. With the divide10.js file in place, I see a transformation of name divide10.js. Using that name in .things, there’s no more error messages.
Unfortunately OH is sluggish now that it ‘finds’ the transformation.

Unfortunately I don’t. I’ve not had to fight a lot of these sorts of errors so I’ve never had to look through the call stack to see what loggers, if any, would be relevant. I think I’d put all of org.openhab into DEBUG to see which loggers are relevant and then dial it back to just those.

It won’t help you here, but if you have the JS Scripting add-on installed, in OH 4 you have access to the whole helper library in the transforms meaning you can add console.log statements to your transformations now much more easily.

In OH 3.4.3 (I think) a new transform was added called SCRIPT. This transform was intended to replace the JS Transformation (which only supports Nashorn JS) with one that also supports all the rest of the rules languages.

However, the syntax was awkward. You had to name the files with a “.script” extension regardless of the language being used and the old JS(filename.js) syntax was eliminated.

Sometime around 4.0 M3 I think the syntax was changed to be a bit more reasonable. Now the SCRIPT transform uses the language as the identifier and the file names must end with the name of the language (so they work with IDEs now).

As a consequence, the old JS Transformation syntax has returned so your old JS transformations should work unchanged between OH 3 and OH 4. Furthermore, because GraalVM JS Scripting is backward compatible for JS Transformations, you don’t even need to install the Nashorn JS add-on to make them work.

OH 4.0 M4 introduced managed transforms (defined through the UI) and the syntax to reference those is slightly different. You have to use config:js to tell it that this is a managed JS transformation and because there is no file the “.js” extension is omitted.

That’s the source of your problem I think. @GunMaster is using a managed transform but you are using a file based transform. So the syntax is slightly different. You want to use


The file based syntax is in the docs: Transformations | openHAB but the managed syntax isn’t in the docs yet which probably needs to be fixed.

Note, this transform is simple enough, if you only use it here, you might use an inline JS transformation.

JS(|parseFloat(input) / 10)

I don’t know why it would be sluggish. If you suspect it’s the JS you could try it using Rules DSL and see if that works better. At the very least it would be something to point at where the problem lives (core or the automation add-on).

I believe modbus also comes with a gain profile which could be use in this case, but it’ll be a profile instead of part of the Channel. There was some work to move that profile to become a standard one but I don’t know if that ever got merged.

I believe I found it. It actually wasn’t because of anything with transformations.

Took me nights full o’sweat to find out (because there were no hints where to look after).
Actually it was Java heap usage parameters we have been using on Raspi in a long time, causing memory limitation. Probably the default max heap size changed when moving JDK 11->17.
Patched openHABian to be more generous about that.
Glad I found it in time for OH4.

Just FYI, many users will upgrade their openhab version without reinstalling openHABian so they might get hit by the same issue on upgrading OH.
Actually /etc/default/openhab has a line defining EXTRA_JAVA_OPTS.
Add -Xmx768m, or even larger if your box has more than 1 GB.