[SOLVED] Rule 'Extractor Fan sensor changed': null - another case

I am afraid I did not get your point. Or we misunderstood each other. What I explained in my post above reflects the current implementation …

Well, I’m glad we’ve got to a point where this is now a known thing. Be it good or “bad” - I’ve had a number of rules misbehave which I am sure can be pinned to this. My cron-for-motion one had the exact same logic in it and too failed randomly. Never could get to the bottom of it.

I will try option 3 for clarification and report back.

Question though, you option 3 will effectively give me a read-only copy of the list? I won’t be able to update it. Or, is it a by-ref copy (not sure what the Java equivalent is?)

Should this, as Rich is saying, not be handled internally? Thinking from a data point of view (I’m a database guy by trade) it can become complicated quickly. But it does seem though that the we’ll always have this gotcha lurking?

Cheers

Why would you want to edit a Group’s membership list in this kind of rule?

Not edit the group but an item in the group; it’s value to be updated. If I have a copy of the group, does that imply a copy of the items and therefore the item is not my original item?

C

Maybe I can elaborate.

As I understand it, the source of the bug is that while a user is iterating over the List in MyGroup.members, the List get’s replaced which kills the streaming operations (.filter, .forEach, etc.).

Your solution is to have all Rules developers modify their Rules to save MyGroup.members to a local variable so that they have a local copy of the List which prevents the error from appearing when the List get’s replaced.

My question was whether GroupItem.getMembers() could be modified to return a static copy of the List, thereby removing the imposition on the Rules developers to know and understand this subtle internal implementation details in order to avoid this cryptic error.

In short, almost everyone is currently susceptible to this error and there are hundreds of examples that are susceptible to this error as currently written. But if MyGroup.getMembers() returned a List that doesn’t change out from under us it would fix all of this existing code and future code without requiring a change to the Rules code itself.

I’m not certain this is feasible because I’m only guessing at how the streaming operations in Xtend work (seems like it makes repeated calls to getMembers() instead of calling it once and streaming from that?). But this is a long existing problem that I believe will also be a problem in Scripted Automation. If there is a way we can avoid this problem through a modification to getMembers(), it would be better (IMHO) than the pretty significant amount of work required to write some docs, fix the tutorials, and field the problems like Crispin’s that will continue to crop up as long as we cannot reliably have lines like: MyGroup.members.filter[door | door == CLOSED].

I doubt it’s a read only copy, but what happens is when a new update occurs, a new list is created and replaces .members. By saving .members to a local variable you avoid having the List changed out from under you.

You would never be changing the Group membership by adding/removing Item to the List returned by .members anyway though. It would get wiped out on the next update and adding an Item to a Group requires more modification to the Item Registry that would be skipped if you just added an Item to the List returned by .members.

You can dynamically add an Item to a Group using MyGroup.addMember(myItem).

An Item, no matter how you get to it isn’t really the Item. It’s a pointer to the Item. The real Item resides in the Item registry. You don’t “update” an Item. You postUpdate to the Item. MyItem.state = ON is not a valid way to set the state of an Item (though sometimes it works?). Anyway, you are always working with a copy of the original Item.

Interesting note, this is why you cannot use the Item Object as the key in a HashMap (for example). You are not guaranteed to get an Item Object that has the same hash value so from run run of the rule to the next you may no longer be able to access the value in the map. So always use the Item name instead of the Item object in Maps.

As Rich says, you don’t update the Item you “send it a message” via postUpdate or sendCommand.

People (me included) occasionally use undocumented methods like
myItem.label = "New text"
but to be honest I think even that will work fine.

Well, I am now using option 3 as @cweitkamp suggested and I get this :sob:

2019-12-10 14:52:50.491 [ERROR] [.model.rule.runtime.internal.engine.RuleEngineImpl] - Rule 'Extractor Fan sensor changed': null

For confirmation I now have this:

    val localMembers            = g_ExtractorFanProxy.members
    val itmSplit                = triggeringItem.name.split("_")
    val location                = itmSplit.get(0);
    val itemFan                 = localMembers.findFirst[GenericItem item | item.name == location + "_ExtractorFan"] as SwitchItem
    val itemFanMaxHumidity      = localMembers.findFirst[GenericItem item | item.name == location + "_MaxHumidity"] as NumberItem
    val itemFanMaxTemperature   = localMembers.findFirst[GenericItem item | item.name == location + "_MaxTemp"] as NumberItem
    val itemTemperature         = localMembers.findFirst[GenericItem item | item.name == location + "_Xiaomi_Temperature"] as NumberItem
    val itemHumidity            = localMembers.findFirst[GenericItem item | item.name == location + "_Xiaomi_Humidity"] as NumberItem

It seems that this too creates the error.
The first instance of getting this is this morning at 10:08 am. I changed to to option 3 at 9:28 this morning.
Problem still exists. Will revert back to the registry option.

So I’ve been looking through the logs to find instances of this where it’s happened so I can fix it. It would do away with one of the “odd things happen” cases that I sometimes end up chasing.

I found this one which is part of the scene rules someone posted here. This rule, along with it’s associated items, manages the house and lighting scenes for when I am in or out, bed-time etc.

rule "SCENE Activate Scene"
when 
	Item CNF_SCENE_Activate received command
then
	val state = receivedCommand

	if (state > 0) {
		CNF_SCENE_Result.postUpdate("Start Activating...")
		// get config string from scene item 	
		sSceneItemName = SCENE_ITEM_BASE_NAME + state.toString			
		//logWarn("Scene Activation", "Activing Scene - " + sSceneItemName)
		gScenes?.allMembers.filter(s | s.name.contains(sSceneItemName)).forEach[sceneItem|
		 	sSceneConf = sceneItem.state.toString
//			logWarn("SCENE","Saved Scene Config:" + sceneItem.state.toString)

		]

		//logInfo("SCENE","Saved Scene Config:" + sSceneConf)
		if (sSceneConf!="Uninitialized" && sSceneConf!="") {
			var arrItems = sSceneConf.split(ITEM_SEPARATOR)
			val itemIgnore = ITEM_IGNORE_PREFIX + state.toString
			//logWarn("AAAAA", "Ignoring item " + itemIgnore)
			for (i : arrItems) {
				val itemConf = i.split(INFO_SEPARATOR)
				val itemName = itemConf.get(0)
				val itemState = itemConf.get(1)
				//gLights?.members.filter(s | s.name==itemName).forEach[lightItem|
				//don't send NULLs. NULLS are, in this instance, a string of the word NULL
				gLights?.members.filter(s | s.name==itemName && itemState != "NULL").filter[light | !light.getGroupNames.contains(itemIgnore)].forEach[lightItem|				
//						logWarn("AAAAA", "itemIgnore:" + itemIgnore + " lightItem:" + lightItem.name + " Item Groups:" + lightItem.getGroupNames.toString)

					lightItem.sendCommand(itemConf.get(1))
				]	
			}
			sMsgToSay = "Ok!" 
			say(sMsgToSay)						
		} else {
			logInfo("SCENE","ATTENZIONE: SCENE NOT CONFIGURED YET")
			sMsgToSay = "Scenario " + CNF_SCENE_Activate.state + "non ancora configurato" 
			say(sMsgToSay)						
		}
	}				

	// Update status
	CNF_SCENE_Result.postUpdate("Ok, scene Applied")
	//CNF_SCENE_ResultReset.sendCommand(ON)

end 

It too has some of the “rule : null” errors. In the previous examples we had a findFirst which is simple to replace with the registry looking. However, this is a loop. Or a filter. Or another loop. Or a get Groups.

If this bug we’re talking about is latent within these methods too, then this could be more of an issue?
@rlkoshak @cweitkamp - any suggestions on how to avoid / work around this considering the val x = bla.members did not seem to work.

When I leave the house, this is the rule that turns off all the lights etc. When there is no motion downstairs and it’s after 23h00, this is the rule which puts the house to sleep. Having it not run reliably is like turning off the home automation :laughing:

What we’re saying is that anything that uses myGroup.members... (or allMembers) is at a small risk.
The issue arises only if you try to access the member list at the moment the group is churning through an update due to a member update.

That’s pretty unlikely in the ordinary course of events - but becomes more likely if you’re triggering your rule off of an event that causes an update cycle of the group in question, and that can often be the case.

I see in your rule you have multiple searches of a group, obviously boosts the odds.

I’m pretty sure the odds will vary with your host hardware too - a system struggling to run one thread at a time will probably be less exposed than a big horsepower multi core box.

I’ve got a few rules doing group searches - because the method is more amenable to a “not found” condition than the more direct fetch-by-name. I don’t get the problem because the rules are triggered by unrelated Items, and are searching for the target to “do things” with.

Unfortunately not. If saving the members to a local variable I’m afraid I don’t have any ideas. I’ve never seen this behavior in Scripted Automation yet, but I almost never saw the error in my Rules DSL once Member of triggers became available. I’ve some ideas but as I pursue them I always end up in the same place: I’ve only moved the problem, not solved it.

First I recommend leaving it be and see if you can add some logging to see if the forEach generates the error too, after switching to using the registry to grab your Items first. I’ve no reason to believe it wouldn’t but I’m not sure I understand what is going on here anymore.

Another option could be to reduce the chances you have the error by only looping through the members of the Group once, at the top to make a copy.

val members = newArrayList(gScenes.allMembers) // I think this will work, come back if not

This should reduce the chances that the error occurs since it’s only this copy operation that is at risk. Since it only happens rarely perhaps this would be enough to make it take months or years between errors instead of days. Though I’m not sure it will help much with this Rule as you are looping through different Groups. I would at least try to do it with gLights since you have a lot of filters and forEachs there.

Maybe saving the results of that first filter to a variable would be sufficient. The thing about streaming operations like filter and forEach and the like is that it doesn’t wait for the filter to finish before it starts running the forEach. As soon as it starts getting matches it passes them on to the forEach. This results in significantly more efficient code, but if there is something that goes wrong anywhere along that stream the whole thing falls apart. If you save the result of the first filter to a variable, you will have a copy at that point and the changes happening to the members on the Group can’t hurt you.

But what is getting me is that the CopyOnWriteArrayList that is supposed to being used in GroupItem shouldn’t be giving us this problem in the first place. That’s the whole reason it exists. And if the .members data member is being replaced when the members update, you’d have a local copy so the error shouldn’t happen either. I’m not convinced we really understand exactly what is going on here. I wonder if the problem is how this streaming is working is somehow bypassing that copy on write (e.g. repeatedly calling .members instead of getting the copy when it first starts running.

I wish this were more reproducible on my system. I’d like to see if it works differently in Python. I suspect it works as expected because it uses Python idioms for doing the iterators instead of Xtend streaming idioms.

Another idea would be to spread out your Groups into more Groups so you don’t have to do as many .filters to get down to the list of Items you want to work on.

1 Like

I would add a possible avoidance technique - where you trigger a rule from whatever, but whatever is itself the cause of (or associated with the cause of) the target group(s) update churning … just wait a bit.

On a powerful machine a simple thread sleep of 50mS should do it.

I’m not so sure that would be as effective on a less potent machine. Because sleep ties a thread up, the group update may itself be blocked from completing. I would recommend the more complex way of setting up a timer to do the rule action in a 100mS or so.

A further point, I missed the significance of your use of allMembers earlier. That’s an implication that you have nested groups. Obviously there’s a lot more churning going on there, for each of the iterative updates of a “child” group we’ll be doing updates of the “parent” group as well.

Data design and rule structure is going to make big differences to risk.

Thanks for the replies chaps.

Just to confirm, have you got my example above to throw the error?

This has been bugging me a bit. I don’t recall the error a few months ago when running on a 3b+. Certainly not the scene one.
In the last 4 days worth of logs I just happened to notice the errors. Granted, in the last few months my system has changed a lot…

I’m still confused why its not affecting more people

It only occurs when you happen to be in the middle of iterating over a group’s members at the exact time that a Group is updating. Depending on the speed of the machine you are looking at a 10-50 millisecond window where those two will line up. And like rossko57 said, most of us have rules triggered and when in such a way that the groups we are iterating over are highly unlikely to be changing when we iterate over them. I saw this error years ago before Member of triggers because the only way to find out what Item triggered a rule was to use received update to the the rule and last update() to filter on the members to see which one changed most recently. But even then, I’d very rarely see the error.

I was unable to generate the error with you’re example, but I’m on a fast machine.

I’m not surprised more people are not reporting this.

I will think about that. But first of all we have to make sure that this is the real cause. I have to admit that I am not 100% sure if myGroup.members uses the getMembers() method or if the framework reflects the property members onto it. XTEXT/XTEND is quite a dark hole for me.

@CDriver First of all I like to thank you for your testing.

One idea which came to my mind which could prove if the issue is related to the group members is to add a general exception handling to your rules. This eventually will lead us to the real cause - It maybe could be caused by something completely different.

...
then
    try {

        // TODO do your stuff

    } catch(Exception e) {
        logError("test", "An exception occurred: {}", e.getMessage(), e)
    }
end

Meh. I am doing the easy part. You guys are making it happen :+1: :slight_smile:

I’ll revert the code and put the try-catch in and report back any info that it might give.

C

I think (emphasis on think) that because the members data member is protected the only way to get at it is through the getMembers method. Xtend has lots of maddening little shortcuts and one of them is if you have the method “getFoo()” you can call it with just “foo” (e.g. MyItem.foo).

Unfortunately, I’m about 90% certain that the exception never gets thown back up the stack into the Rule where it can be caught. This is definitely the case with other “null” errors the Rules DSL reports (e.g. type errors). That’s one of the reasons why ReentrantLocks are not safe to use, you can’t guarantee that a finally clause gets executed.

It will be very illuminating to find out if this is one such error though so do please add the try/catch and let’s see what happens.

I spent a really long time looking into this years ago, though I certainly didn’t know as much then as I do now, and for me it was also occurring inside a lambda and I was running on a much slower machine. Eventually I found a better way to do the same thing and the errors went away and now I can’t even force it to happen, at least using Crispin’s exemplar. But this error was the bane of my existence for quite awhile.

I know there is a lot going on preparing for the release of 2.5 and this is a problem we’ve lived with since OH 1.6 at least, probably forever. Would you like me to open an issue to capture what we’ve discovered so far?

I think I’ve caught one!
I set up a group with some numbers, and a pair of rules that when triggered fire off a further series of updates to the Items while using members.findFirst on the same group. Details don’t matter here, but it makes a little storm of a 20 or so rule executions against the background of normal system work for each trigger.

Actual test lines are simply of the form
val local1 = gBananas.members.findFirst[ i | i.name=="test1"]

About every tenth or so attempt of manually triggering a half dozen storms … I get a null.
OH 2.4 , Oracle java , win 7
And with a
try { …
} catch(Throwable e) {
in place …

2019-12-13 22:48:48.296 [ERROR] [.eclipse.smarthome.model.script.test] - An exception occurred: null
java.lang.IllegalStateException: null
	at org.eclipse.xtext.xbase.typesystem.references.UnboundTypeReference.doCopyInto(UnboundTypeReference.java:677) ~[?:?]
	at org.eclipse.xtext.xbase.typesystem.references.UnboundTypeReference.copyInto(UnboundTypeReference.java:433) ~[?:?]
	at org.eclipse.xtext.xbase.typesystem.internal.ResolvedTypes.toOwnedReference(ResolvedTypes.java:599) ~[?:?]
	at org.eclipse.xtext.xbase.typesystem.internal.ResolvedTypes.getExpectedType(ResolvedTypes.java:622) ~[?:?]
	at org.eclipse.xtext.xbase.typesystem.internal.ForwardingResolvedTypes.getExpectedType(ForwardingResolvedTypes.java:90) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:205) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:190) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29) ~[?:?]
	at com.sun.proxy.$Proxy172.apply(Unknown Source) ~[?:?]
	at org.eclipse.xtext.xbase.lib.IteratorExtensions.findFirst(IteratorExtensions.java:108) ~[?:?]
	at org.eclipse.xtext.xbase.lib.IterableExtensions.findFirst(IterableExtensions.java:80) ~[?:?]
	at sun.reflect.GeneratedMethodAccessor413.invoke(Unknown Source) ~[?:?]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:?]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:1086) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:1061) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1047) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:992) ~[?:?]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:151) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:772) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:220) ~[?:?]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:204) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:827) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:264) ~[?:?]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:204) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:447) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:228) ~[?:?]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:204) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:626) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:260) ~[?:?]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:204) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:447) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:228) ~[?:?]
	at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:204) ~[?:?]
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:190) ~[?:?]
	at org.eclipse.smarthome.model.script.runtime.internal.engine.ScriptImpl.execute(ScriptImpl.java:82) ~[?:?]
	at org.eclipse.smarthome.model.rule.runtime.internal.engine.RuleEngineImpl.lambda$2(RuleEngineImpl.java:341) ~[?:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:?]
	at java.util.concurrent.FutureTask.run(Unknown Source) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:?]
	at java.lang.Thread.run(Unknown Source) [?:?]

Means nothing to me but I see
org.eclipse.xtext.xbase.lib.IteratorExtensions.findFirst
in there so confident it is the right error

@rlkoshak Yes, I can imagine how challenging it is to tackle down such an issue. I tried the same more than once - sometimes successful - most of the times not.

@rossko57 I remember that I saw similar errors (e.g.
IllegalStateException in xtext rule engine when using getThingStatusInfo() inside a lambda and triggeringItem problem (concurrency?)). Currently I do not have an idea on that too.

How ironic. Found something in the logs of my own live environment too. Same situation. I am iterating over members of a group in a rule / script. I cannot remember the last time this happened but it probably did because I am using the try - catch - block inside.

2019-12-13 08:01:32.446 [ERROR] [org.quartz.core.ErrorLogger         ] - Job (DEFAULT.Timer 90 2019-12-13T08:01:32.367+01:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
  logInfo(<XStringLiteralImpl>,<XStringLiteralImpl>,<XMemberFeatureCallImplCustom>,<XMemberFeatureCallImplCustom>,<XMemberFeatureCallImplCustom>)
  val darken
  org.eclipse.xtext.xbase.impl.XIfExpressionImpl@599a16 (conditionalExpression: false)
  <null>.kodiLivingRoomTimer = <XNullLiteralImplCustom>
} ] threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception.
        at org.quartz.core.JobRunShell.run(JobRunShell.java:213) [bundleFile:?]
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [bundleFile:?]
Caused by: java.lang.IllegalStateException
        at org.eclipse.xtext.xbase.typesystem.references.UnboundTypeReference.doCopyInto(UnboundTypeReference.java:684) ~[?:?]
        at org.eclipse.xtext.xbase.typesystem.references.UnboundTypeReference.copyInto(UnboundTypeReference.java:440) ~[?:?]
        at org.eclipse.xtext.xbase.typesystem.internal.ResolvedTypes.toOwnedReference(ResolvedTypes.java:599) ~[?:?]
        at org.eclipse.xtext.xbase.typesystem.internal.ResolvedTypes.getExpectedType(ResolvedTypes.java:622) ~[?:?]
        at org.eclipse.xtext.xbase.typesystem.internal.ForwardingResolvedTypes.getExpectedType(ForwardingResolvedTypes.java:90) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:216) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:458) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:239) ~[?:?]
        at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:201) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:1168) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:1150) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1136) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:1081) ~[?:?]
        at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:151) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:861) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:231) ~[?:?]
        at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:916) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:275) ~[?:?]
        at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:458) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:239) ~[?:?]
        at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:226) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:215) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:201) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[?:?]
        at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29) ~[?:?]
        at com.sun.proxy.$Proxy3215.apply(Unknown Source) ~[?:?]
        at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:48) ~[?:?]
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[?:?]
        ... 1 more