Skip to main content

How to Fix ‘no handler for device.send()’ Errors

Understanding Unexpected Agent-device Miscommunication

When agent code calls device.send() and there is no equivalent agent.on() in the device code, the device will log a error like this:

2015-07-07 19:54:17 UTC-5  [server.error]  ERROR: no handler for device.send()

This may seem odd, since the device can’t call device.send(), but it’s simply a sign that the device has received a message transmitted by a device.send() from the agent.

The usual way to debug this is to compare all the instances of device.send() in the agent code to ensure they are accompanied by an agent.on(). The first parameter of both calls, a string containing an identifier for the message being sent, must match across the two paired calls. A common source of error is a mis-typed message name string in either of the two calls.

What if you have eliminated such issues as causes of the error? In this case, it may be that you are experiencing a race condition. If, for instance, your agent code calls device.send() as soon as it boots, but the paired agent.on() is near the bottom of your device code, the message can be sent and received before the device’s Squirrel interpreter has been able to register the handler function you assign in the agent.on() call. Because the code hasn’t yet performed this registration when the message arrives, it will throw the above error.

If this is the case, you can apply any of the following techniques:

  • Register the device’s message handlers as early as possible in the code sequence.

  • Delay the device.send() call on the agent side to allow the device time to complete its setup. For example:

imp.wakeup(1, function() {
  // Wait 1 second for the device to boot before
  // sending it the first message
  device.send("my.message", data);
});
  • Have the device signal its readiness to the agent and ensure that no messages are sent from agent to device until this signal has been received. For example:
device.on("ready", function() {
  // Device has signalled its readiness - send over saved settings
  device.send("clock.set.preferences", settingsTable);
});

An equivalent error involves a missing handler for agent.send() posted by the agent. Again, this is caused by either a message from the device arriving before its intended handler function has been registered, or the other causes described above.