Error handling
Every driver run ends in exactly one D.success() or D.failure(D.errorType.X). The failure taxonomy is narrow on purpose — the portal uses it to distinguish transient problems from real outages in dashboards and alerts.
Error types
Section titled “Error types”D.errorType.* | When to use |
|---|---|
RESOURCE_UNAVAILABLE | Device is unreachable. Ping fails, TCP connect refused, endpoint 5xx, SSH connect timeout, SNMP no-response. |
AUTHENTICATION_ERROR | Credentials rejected. HTTP 401/403, SSH bad-key, SNMP v3 auth failure, Telnet password prompt not satisfied. |
PARSING_ERROR | Response came back but its structure is wrong. JSON.parse threw, regex didn’t match, expected field missing. |
TIMEOUT_ERROR | Operation ran past its own timeout. Prefer over RESOURCE_UNAVAILABLE when the device answered something before the cut-off. |
GENERIC_ERROR | Anything else. Use sparingly — the others cover 95% of real cases. |
One success/failure per run
Section titled “One success/failure per run”Drivers get one shot. These shapes are wrong and will leak or double-report:
// wrong: both paths call somethingfunction get_status() { D.device.http.get({ url: '/a' }, function (err) { if (err) D.failure(D.errorType.RESOURCE_UNAVAILABLE); D.success(); });}// right: else or early returnfunction get_status() { D.device.http.get({ url: '/a' }, function (err) { if (err) return D.failure(D.errorType.RESOURCE_UNAVAILABLE); D.success(); });}Fan-out + single terminal call
Section titled “Fan-out + single terminal call”When you make multiple calls in parallel, track completion and call D.success / D.failure exactly once:
function get_status() { var pending = 2; var failed = false; var results = {};
function fail(type) { if (failed) return; failed = true; D.failure(type); }
function done(key, value) { if (failed) return; results[key] = value; pending -= 1; if (pending === 0) D.success([ D.createVariable('temp', 'Temperature', results.temp, 'C', D.valueType.NUMBER), D.createVariable('load', 'Load', results.load, '%', D.valueType.NUMBER) ]); }
D.device.sendSSHCommand({ command: 'sensors -u' }, function (out, err) { if (err) return fail(D.errorType.RESOURCE_UNAVAILABLE); done('temp', parseTemp(out)); }); D.device.sendSSHCommand({ command: 'uptime' }, function (out, err) { if (err) return fail(D.errorType.RESOURCE_UNAVAILABLE); done('load', parseLoad(out)); });}Timeouts are not errors
Section titled “Timeouts are not errors”If a device is slow but ultimately responds, that’s a healthy signal. If a device never responds within the driver’s timeout, prefer TIMEOUT_ERROR over RESOURCE_UNAVAILABLE — it helps dashboards distinguish slow from dead.
Do not retry in the driver
Section titled “Do not retry in the driver”Every tick is an independent retry. Don’t build retry loops into the driver — they burn the per-run wall clock for no dashboard benefit. If a call fails, call D.failure and let the next tick try again.
Logging
Section titled “Logging”console.error messages land in the collector log. They are visible to anyone debugging the driver but are not sent to the portal. Keep them short, factual, and free of credentials.
console.error('HTTP', response.statusCode, 'from', options.url);See Testing & debugging for where those logs show up on the collector host.