louislam/uptime-kuma · error · Error
Expected TLS alert '${expectedTlsAlert}' but got unexpected
Error message
Expected TLS alert '${expectedTlsAlert}' but got unexpected error: ${result.errorMessage} What it means
Final else branch of checkTlsAlert (tcp.js:332-335). attemptTlsConnection returned success:false but parseTlsAlertNumber could not extract a numeric alert (alertNumber === null), so the failure is not a recognizable TLS alert — it is a transport/parse-level error surfaced verbatim in result.errorMessage.
Source
Thrown at server/monitor-types/tcp.js:333
await monitor.handleTlsInfo(result.tlsInfo);
}
// Check if we got the expected alert
// Note: Error messages below could be translated, but alert names (e.g., certificate_required)
// are from RFC 8446 spec and should remain in English for consistency with the spec.
if (result.alertName === expectedTlsAlert) {
heartbeat.status = UP;
heartbeat.msg = `TLS alert received as expected: ${result.alertName} (${result.alertNumber})`;
} else if (result.success) {
throw new Error(
`Expected TLS alert '${expectedTlsAlert}' but connection succeeded. The server accepted the connection without requiring a client certificate.`
);
} else if (result.alertNumber !== null) {
throw new Error(
`Expected TLS alert '${expectedTlsAlert}' but received '${result.alertName}' (${result.alertNumber})`
);
} else {
throw new Error(
`Expected TLS alert '${expectedTlsAlert}' but got unexpected error: ${result.errorMessage}`
);
}
}
/**
* Attempt TLS connection and capture result/alert
* @param {object} monitor Monitor object
* @param {object} options TLS connection options
* @param {number} startTime Connection start timestamp
* @param {number} timeout Connection timeout in ms
* @returns {Promise<object>} Connection result with success, responseTime, tlsInfo, alertNumber, alertName, errorMessage
*/
attemptTlsConnection(monitor, options, startTime, timeout) {
return new Promise((resolve, reject) => {
const socket = tls.connect(options);
const timeoutId = setTimeout(() => {View on GitHub (pinned to 6b5ea01557)
Solutions
- Inspect result.errorMessage in the heartbeat for the true cause (e.g. ECONNREFUSED, getaddrinfo ENOTFOUND).
- Confirm host/port reachability with `nc -vz host port` or `openssl s_client`.
- If the error looks like a TLS alert but no number was parsed, check whether a newer Node version changed the message shape and report/patch parseTlsAlertNumber.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight DNS + TCP so transport errors surface as transport, not as alert-check failures
const dns = require('dns').promises;
const net = require('net');
async function endpointReady(host, port) {
await dns.lookup(host); // throws on DNS failure
return new Promise((res) => {
const s = net.createConnection({ host, port });
s.setTimeout(5000);
s.on('connect', () => { s.destroy(); res(true); });
s.on('error', () => res(false));
s.on('timeout', () => { s.destroy(); res(false); });
});
} Type guard
function isAttemptResult(v) {
return v != null && typeof v === 'object'
&& typeof v.success === 'boolean'
&& (v.alertNumber === null || typeof v.alertNumber === 'number')
&& (typeof v.errorMessage === 'string' || v.errorMessage == null);
} Try / catch
try {
await monitor.checkTlsAlert(monitor, heartbeat, expectedTlsAlert);
} catch (e) {
if (/got unexpected error/.test(e.message)) {
const inner = e.message.split('error:')[1]?.trim();
heartbeat.msg = `Transport-level TLS failure (no alert): ${inner}`;
}
} Prevention
- Separate transport reachability from TLS-alert semantics in your alerts.
- Log parseTlsAlertNumber hits/misses so a parser regression is visible.
When it happens
Trigger: Connection reset before any TLS byte (firewall RST), DNS failure surfaced through tls.connect's error event, ECONNREFUSED, or an error string format Node changed so the regex in parseTlsAlertNumber no longer extracts the number.
Common situations: Host down or port closed; intermediate proxy does not speak TLS on that port; Node.js version upgrade altered the error message format, breaking the alert-number parser.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- TLS Connection failed: ${message}
- Expected TLS alert '${expectedTlsAlert}' but connection succ
- Expected TLS alert '${expectedTlsAlert}' but received '${res
- ${error.message}
- SMTP connection doesn't verify: ${e}
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/aa8c885accfaec5a.
Report an issue: GitHub.