louislam/uptime-kuma · error · Error
Error checking Tailscale ping
Error message
Error checking Tailscale ping: ${err} What it means
Top-level catch-all inside TailscalePing.check(). It wraps any error thrown by runTailscalePing() (spawn failure, stderr output, empty output) or parseTailscaleOutput() (timed out, ACL, unexpected line) into a single 'Error checking Tailscale ping' message that carries the original cause in its string. The original error is concatenated rather than chained via .cause, so structured detail is lost.
Solutions
- Read the inner error text to identify which specific failure occurred (ENOENT, timeout, 'no matching peer', etc.) and address that root cause.
- Ensure the 'tailscale' binary is installed and on PATH for the Uptime-Kuma process.
- Confirm tailscaled is running and logged in: 'tailscale status'.
- If migrating to structured errors, wrap with `new Error(msg, { cause: err })` so the original is inspectable.
Example fix
// before
} catch (err) {
throw new Error(`Error checking Tailscale ping: ${err}`);
}
// after — preserve the cause chain for diagnostics
} catch (err) {
throw new Error(`Error checking Tailscale ping: ${err.message}`, { cause: err });
} Defensive patterns
Strategy: try-catch
Validate before calling
const fs = require("fs");
function tailscaleAvailable() {
try { require("child_process").execFileSync("tailscale", ["--version"], { stdio: "ignore" }); return true; }
catch { return false; }
} Type guard
function isTailscaleError(e) { return /Tailscale/.test(e?.message || ""); } Try / catch
try { ... }
catch (err) {
heartbeat.status = DOWN;
heartbeat.msg = `Error checking Tailscale ping: ${err.message}`;
// throw new Error(..., { cause: err }) if re-throwing
} Prevention
- Ensure the tailscale CLI is installed and tailscaled is logged in.
- Use { cause } when wrapping to preserve diagnostics.
- Surface the inner error message to the user instead of only the generic wrapper.
When it happens
Trigger: Produced for ANY failure during a tailscale-ping monitor cycle: 'tailscale' binary not found, spawn ENOENT, command timeout, non-zero exit with stderr, empty stdout, or any unrecognised line in the parsed output.
Common situations: Tailscale CLI not installed on the Uptime-Kuma host; tailscaled not running or not logged in; ACLs blocking the target; the monitor hostname is the machine's own Tailscale IP; the target node is offline; the installed tailscale version emits output the parser does not recognise.
Related errors
- Error in output
- No output from Tailscale ping
- Nonexistant or inaccessible due to ACLs
- Ping timed out
- Tailscale only works if used on other machines
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/cddc314e7d674de2.
Report an issue: GitHub.
Appendix: source
Thrown at server/monitor-types/tailscale-ping.js:17
const { MonitorType } = require("./monitor-type");
const { UP } = require("../../src/util");
const childProcessAsync = require("promisify-child-process");
class TailscalePing extends MonitorType {
name = "tailscale-ping";
/**
* @inheritdoc
*/
async check(monitor, heartbeat, _server) {
try {
let tailscaleOutput = await this.runTailscalePing(monitor.hostname, monitor.interval);
this.parseTailscaleOutput(tailscaleOutput, heartbeat);
} catch (err) {
// trigger log function somewhere to display a notification or alert to the user (but how?)
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()}`);View on GitHub (pinned to 6b5ea01557)