louislam/uptime-kuma · error · Error
SMSEagle API returned error
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.
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
- Invalid VK API response
- SMSEagle API returned an empty response
- SMSEagle API returned error
- yzj's server did not respond with the expected result
- Additional Headers is not a valid JSON
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/a916e442aff04d38.
Report an issue: GitHub.
Appendix: 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)