louislam/uptime-kuma · error · Error
SMSEagle API returned error: ${JSON.stringify(resp.data)}
Error message
SMSEagle API returned error: ${JSON.stringify(resp.data)} What it means
Thrown by the SMSEagle apiv2 path when the response is non-200 or zero recipients queued, but resp.data is a non-empty array. Each array element is a per-recipient status object; if none has status 'queued' (e.g. all 'rejected', 'failed', 'invalid'), the entire JSON payload is stringified into the error so the operator can see which recipients failed and why.
Source
Thrown at server/notification-providers/smseagle.js:129
endpoint = "/calls/ring";
} else if (notification.smseagleMsgType === "smseagle-tts") {
endpoint = "/calls/tts";
} else if (notification.smseagleMsgType === "smseagle-tts-advanced") {
endpoint = "/calls/tts_advanced";
postData["voice_id"] = notification.smseagleTtsModel ?? 1;
}
}
let resp = await axios.post(notification.smseagleUrl + "/api/v2" + endpoint, postData, config);
const queuedCount = resp.data.filter((x) => x.status === "queued").length;
const unqueuedCount = resp.data.length - queuedCount;
if (resp.status !== 200 || queuedCount === 0) {
if (!resp.data.length) {
throw new Error("SMSEagle API returned an empty response");
}
throw new Error(`SMSEagle API returned error: ${JSON.stringify(resp.data)}`);
}
if (unqueuedCount) {
return `Sent ${queuedCount}/${resp.data.length} Messages Successfully.`;
}
return okMsg;
}
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = SMSEagle;
View on GitHub (pinned to 6b5ea01557)
Solutions
- Read the JSON in the error: each object's status/message field names the failing recipient and reason.
- Remove or correct the specific recipients flagged as rejected/failed in the payload.
- Top up SMS credits on the device SIM and confirm the modem is online.
- If the device firmware renamed the status value, update the queuedCount filter (smseagle.js:122) to also accept the new value (e.g. 'accepted').
Defensive patterns
Strategy: try-catch
Type guard
/** True when every recipient object carries a recognizable status. */
function isSmseagleV2OutcomeArray(data) {
return Array.isArray(data) && data.every((x) => x && ["queued","sent","rejected","failed","invalid"].includes(x.status));
} Try / catch
try {
const resp = await axios.post(url, postData, config);
const queued = Array.isArray(resp.data) ? resp.data.filter((x) => x.status === "queued").length : 0;
if (resp.status !== 200 || queued === 0) {
throw new Error(`SMSEagle API returned error: ${JSON.stringify(resp.data)}`);
}
} catch (err) {
this.throwGeneralAxiosError(err);
} Prevention
- Keep recipient lists current; prune retired numbers periodically.
- Monitor device credit/modem status from the SMSEagle UI.
- Track the firmware 'queued' status name across upgrades.
When it happens
Trigger: All recipients rejected by the device (invalid number, blocked, duplicate, quota exhausted), a 4xx from the gateway with a structured error array, or recipients marked 'sent'/'delivered' but never 'queued' (status filter mismatch after a firmware change).
Common situations: Recipient list contains stale numbers, device SIM out of credit, recipients on a blocklist, or firmware upgrade renaming 'queued' to 'accepted' so the filter returns zero.
Related errors
- SMSEagle API returned error: ${resp.data}
- SMSEagle API returned an empty response
- Invalid VK API response
- yzj's server did not respond with the expected result
- user not found, have you installed?
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/a916e442aff04d38.
Report an issue: GitHub.