{"record":{"id":"dd901e54f6d984b2","repo":"louislam/uptime-kuma","slug":"tls-connection-failed-message","errorCode":null,"errorMessage":"TLS Connection failed: ${message}","messagePattern":"TLS Connection failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/monitor-types/tcp.js","lineNumber":273,"sourceCode":"                    }\n                });\n\n                socket.on(\"error\", (error) => {\n                    reject(error);\n                });\n\n                socket.setTimeout(1000 * TIMEOUT, () => {\n                    reject(new Error(\"Connection timed out\"));\n                });\n            });\n\n            await monitor.handleTlsInfo(tlsInfoObject);\n            if (!tlsInfoObject.valid) {\n                throw new Error(\"Certificate is invalid\");\n            }\n        } catch (error) {\n            const message = error instanceof Error ? error.message : \"Unknown error\";\n            throw new Error(`TLS Connection failed: ${message}`);\n        } finally {\n            if (socket && !socket.destroyed) {\n                socket.end();\n            }\n        }\n    }\n\n    /**\n     * Check for expected TLS alert (for mTLS verification)\n     * @param {object} monitor Monitor object\n     * @param {object} heartbeat Heartbeat object\n     * @param {string} expectedTlsAlert Expected TLS alert name\n     * @returns {Promise<void>}\n     */\n    async checkTlsAlert(monitor, heartbeat, expectedTlsAlert) {\n        const timeout = monitor.timeout * 1000 || 30000;\n        const startTime = Date.now();\n","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/monitor-types/tcp.js#L255-L291","documentation":"Wraps every failure path inside checkTlsCertificate (tcp.js:236-279). The outer try/catch re-throws any underlying error — TLS handshake error, the 'Connection timed out' from socket.setTimeout (line 263), a checkCertificate failure, or the explicit 'Certificate is invalid' (line 269) — prefixed with 'TLS Connection failed: '. It exists so the monitor heartbeat surfaces one consistent error family regardless of which sub-step broke.","triggerScenarios":"Calling tls.connect against an unreachable/filtered host (timeout fires), a server whose certificate is self-signed/expired/chain-incomplete when rejectUnauthorized is on, a hostname mismatch (SNI vs cert CN/SAN), or a STARTTLS negotiation that the server refuses.","commonSituations":"Monitoring an internal service behind a self-signed cert without toggling 'ignore TLS', a renewed cert whose intermediate chain was not bundled, a hostname recently changed in DNS but the monitor still points at the old one, firewall egress blocking the TLS port so the 1.5xTIMEOUT socket timer fires.","solutions":["Read the inner ${message} first — it pinpoints which sub-step failed (timeout vs invalid cert vs handshake error).","If the message is 'Certificate is invalid' or names a cert problem, open the host in a browser or `openssl s_client -connect host:port -servername host` to inspect the chain/expiry.","If the message is 'Connection timed out', verify network reachability and that monitor.hostname/port are correct.","For self-signed/internal CAs, set the monitor's ignore-TLS option or supply the CA via the monitor's tls_ca field instead of disabling validation.","Increase monitor.timeout if the host legitimately needs longer than TIMEOUT seconds to complete the handshake."],"exampleFix":"// before: monitor points at host with self-signed cert and rejectUnauthorized on\n// after: configure the monitor to trust the internal CA\nmonitor.tls_ca = fs.readFileSync('/etc/ssl/internal-ca.pem');\nmonitor.ignoreTls = false;","handlingStrategy":"try-catch","validationCode":"// Pre-flight reachability + cert sanity before relying on checkTlsCertificate\nconst net = require('net');\nfunction hostReachable(host, port, ms = 5000) {\n    return new Promise((res) => {\n        const s = net.createConnection({ host, port });\n        s.setTimeout(ms);\n        s.on('connect', () => { s.destroy(); res(true); });\n        s.on('error', () => res(false));\n        s.on('timeout', () => { s.destroy(); res(false); });\n    });\n}\nif (!(await hostReachable(monitor.hostname, monitor.port))) {\n    throw new Error(`Host unreachable: ${monitor.hostname}:${monitor.port}`);\n}","typeGuard":"function isTlsInfoObject(v) {\n    return v != null && typeof v === 'object'\n        && typeof v.valid === 'boolean'\n        && 'certInfo' in v;\n}","tryCatchPattern":"try {\n    await monitor.checkTlsCertificate(monitor);\n} catch (e) {\n    // unwrap: 'TLS Connection failed: <reason>'\n    const reason = e.message.startsWith('TLS Connection failed:') ? e.message.slice('TLS Connection failed:'.length).trim() : e.message;\n    heartbeat.status = reason.includes('timed out') ? PENDING : DOWN;\n    heartbeat.msg = reason;\n}","preventionTips":["Whitelist internal CAs via monitor.tls_ca instead of disabling verification globally.","Keep monitor.timeout comfortably above the slowest expected TLS handshake for the target.","Run a TCP pre-flight before TLS to separate reachability from cert problems."],"tags":["tls","certificate","tcp-monitor","network","timeout"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}