You did, or rather your rule did. When you use createTimer() you are scheduling an independent job for the future.
Because timers are fully independent of the rule that spawned them, the error messaging is always a bit vague.
You do get a sort of skeleton of the timer code processed so far - so in the error you show us, it’s fallen down trying to do something to do with sendCommand.
That doesn’t help us a great deal here, as all your timer code blocks begin with a sendCommand.
The actual error - something was unexpectedly null - is fairly universal for a timer error, once you get over basic syntax errors.
I’m going to make a guess that these are fairly long-running timers, and that you have been editing your new rules while setting them up and testing.
You need to bear the “orphaned timer” effect in mind as the most likely culprit here -
But you should also consider
BW_Z2_StartTimer = createTimer(startTime) [| ...
the timer does NOT “live” in the variable BW_Z2_StartTimer, it’s fully independent remember.
The variable just holds a pointer or handle for the timer proper. So you could come along later and rewrite that variable with something else, that will not affect the previously linked timer which will still run at the appointed time.
One way to do that is to run the rule containing
BW_Z2_StartTimer = createTimer(startTime) [| ...
again, making a new timer linked to the handle variable, but not stopping the previous one.
Your rule is able to do that, so be careful.
The way to avoid that is to write the rule so that it examines the handle variable first, to find out if there is an existing timer. It can then decide to reschedule or cancel it.
This way to work is the whole point of setting the handle variable to null after you really have executed or cancelled the timer.