{"record":{"id":"0e10864935d46a3b","repo":"louislam/uptime-kuma","slug":"error-in-output-stderr-tostring","errorCode":null,"errorMessage":"Error in output: ${stderr.toString()}","messagePattern":"Error in output: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/monitor-types/sip-options.js","lineNumber":38,"sourceCode":"    }\n\n    /**\n     * Runs Sipsak options ping\n     * @param {string} hostname SIP server address to send options.\n     * @param {number} port SIP server port\n     * @param {number} timeout timeout of options reply\n     * @returns {Promise<string>} A Promise that resolves to the output of the Sipsak options ping\n     * @throws Will throw an error if the command execution encounters any error.\n     */\n    async runSipSak(hostname, port, timeout) {\n        const { stdout, stderr } = await execFile(\n            \"sipsak\",\n            [\"-s\", `sip:${hostname}:${port}`, \"--from\", `sip:sipsak@${hostname}`, \"-v\"],\n            { timeout }\n        );\n\n        if (!stdout && stderr && stderr.toString()) {\n            throw new Error(`Error in output: ${stderr.toString()}`);\n        }\n        if (stdout && stdout.toString()) {\n            return stdout.toString();\n        } else {\n            throw new Error(\"No output from sipsak\");\n        }\n    }\n\n    /**\n     * @param {string} res response to be parsed\n     * @param {object} heartbeat heartbeat object to update\n     * @returns {void} returns nothing\n     */\n    parseSipsakResponse(res, heartbeat) {\n        let lines = res.split(\"\\n\");\n        for (let line of lines) {\n            if (line.includes(\"200 OK\")) {\n                heartbeat.status = UP;","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/monitor-types/sip-options.js#L20-L56","documentation":"runSipSak shells out to the `sipsak` binary with -s sip:host:port, --from, and -v. If the child produced no stdout but did produce stderr, the monitor treats stderr as a hard failure and throws it prefixed with 'Error in output:'. This surfaces sipsak's own diagnostics instead of silently succeeding.","triggerScenarios":"execFile resolves but stdout is empty and stderr is non-empty: sipsak emitted an error/warning to stderr (e.g. 'target host unknown', TLS errors, or malformed SIP URI). The branch at sip-options.js:38 fires.","commonSituations":"Wrong port, target not a SIP server, DNS issues, sipsak built without TLS for a sips: target, or firewall dropping SIP packets such that sipsak errors out.","solutions":["Run sipsak manually with the same arguments to read the stderr: sipsak -s sip:host:port --from sip:sipsak@host -v.","Confirm the host/port is a reachable SIP server.","Install/build sipsak with TLS support if targeting sips: URIs.","Check firewall rules for the SIP signalling port (UDP/TCP 5060, 5061)."],"exampleFix":"# before\nError in output: target 'sip:bad.host:5060' unknown\n# after\n# correct the hostname/port in the monitor","handlingStrategy":"validation","validationCode":"const { execFile } = require('child_process');\nconst util = require('util');\nconst execFileP = util.promisify(execFile);\nasync function preflightSipsak(host, port) {\n  try {\n    await execFileP('sipsak', ['-V']); // version probe; fails if binary missing\n  } catch {\n    throw new Error('sipsak binary not installed');\n  }\n}","typeGuard":"function hasSipsakStderr(out) { return !!out && !out.stdout && !!out.stderr; }","tryCatchPattern":"try {\n  await runSipSak(hostname, port, timeout);\n} catch (e) {\n  if (/^Error in output:/.test(e.message)) {\n    // surface sipsak stderr verbatim for diagnosis\n  }\n  throw e;\n}","preventionTips":["Install sipsak (apt install sipsak) on the host/container.","Confirm host:port is a real SIP server before scheduling the monitor.","Build sipsak with TLS if you target sips: URIs."],"tags":["sip","sipsak","network","subprocess"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}