louislam/uptime-kuma · error · Error

Error in output: ${res.stderr.toString()}

Error message

Error in output: ${res.stderr.toString()}

What it means

Thrown by runTailscalePing() after the spawn of 'tailscale ping' completed (did not throw) but wrote to stderr and exited with a non-zero code. promisify-child-process resolves the spawn with {stdout, stderr, code}; this branch converts a failed exit into an explicit error using the stderr text.

Source

Thrown at server/monitor-types/tailscale-ping.js:35

            throw new Error(`Error checking Tailscale ping: ${err}`);
        }
    }

    /**
     * Runs the Tailscale ping command to the given URL.
     * @param {string} hostname The hostname to ping.
     * @param {number} interval Interval to send ping
     * @returns {Promise<string>} A Promise that resolves to the output of the Tailscale ping command
     * @throws Will throw an error if the command execution encounters any error.
     */
    async runTailscalePing(hostname, interval) {
        let timeout = interval * 1000 * 0.8;
        let res = await childProcessAsync.spawn("tailscale", ["ping", "--c", "1", hostname], {
            timeout: timeout,
            encoding: "utf8",
        });
        if (res.stderr && res.stderr.toString() && res.code !== 0) {
            throw new Error(`Error in output: ${res.stderr.toString()}`);
        }
        if (res.stdout && res.stdout.toString()) {
            return res.stdout.toString();
        } else {
            throw new Error("No output from Tailscale ping");
        }
    }

    /**
     * Parses the output of the Tailscale ping command to update the heartbeat.
     * @param {string} tailscaleOutput The output of the Tailscale ping command.
     * @param {object} heartbeat The heartbeat object to update.
     * @returns {void}
     * @throws Will throw an eror if the output contains any unexpected string.
     */
    parseTailscaleOutput(tailscaleOutput, heartbeat) {
        let lines = tailscaleOutput.split("\n");

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Run 'tailscale ping --c 1 <hostname>' manually as the Uptime-Kuma user to reproduce and read the stderr message.
  2. Ensure tailscaled is running and the host is logged in ('tailscale status' should list peers).
  3. Confirm the tailscale CLI version supports the flags used; upgrade or adjust the invocation if '--c' is not accepted.
  4. If running in containers, make sure the tailscale socket/daemon is reachable from the Uptime-Kuma container.
Defensive patterns

Strategy: try-catch

Validate before calling

function isNonZeroExit(res) { return res && res.code !== 0 && res.stderr && res.stderr.toString().trim().length > 0; }

Type guard

function hasStderr(res) { return !!res?.stderr && res.stderr.toString().trim().length > 0; }

Try / catch

if (isNonZeroExit(res)) { heartbeat.status = DOWN; heartbeat.msg = res.stderr.toString().trim(); return; }

Prevention

When it happens

Trigger: Produced when 'tailscale ping --c 1 <hostname>' exits non-zero and prints to stderr: not logged in, tailscaled unreachable, permission denied, unknown flag, or a tailscale daemon error.

Common situations: tailscale daemon not running; the Uptime-Kuma process user cannot invoke tailscale; tailscale version that does not support '--c' syntax; auth expired; node offline in the tailnet; running inside a container without tailscaled sidecar.

Related errors


AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12). Data as JSON: /api/errors/f1a1fd13c0c6bba5. Report an issue: GitHub.