{"record":{"id":"6e093185a14a7b07","repo":"qishibo/AnotherRedisDesktopManager","slug":"this-t-message-test-connection-timeout","errorCode":null,"errorMessage":"this.$t('message.test_connection_timeout')","messagePattern":"this\\.\\$t\\('message\\.test_connection_timeout'\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/components/NewConnectionDialog.vue","lineNumber":440,"sourceCode":"        this.$message.error(message || this.$t('message.test_connection_failed'));\n      }\n    },\n    testConnection() {\n      if (this.testing) {\n        return;\n      }\n\n      const config = this.getConnectionConfig();\n      if (!config) {\n        return;\n      }\n\n      this.testing = true;\n      this.testClient = null;\n\n      // show timeout message after N seconds\n      this.testTimer = setTimeout(() => {\n        this.finishTest(false, this.$t('message.test_connection_timeout'));\n      }, 5000);\n\n      const clientPromise = config.sshOptions\n        ? redisClient.createSSHConnection(\n          config.sshOptions, config.host, config.port, config.auth, config,\n        )\n        : redisClient.createConnection(\n          config.host, config.port, config.auth, config,\n        );\n\n      clientPromise.then((client) => {\n        this.testClient = client;\n        client.options.retryStrategy = () => false;\n\n        // Already finished (timeout/cancel) while creating connection.\n        if (!this.testing) {\n          this.cleanupTestClient();\n          return;","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/qishibo/AnotherRedisDesktopManager/blob/c149855106628babcdfb7675a8e7ba9434d2492a/src/components/NewConnectionDialog.vue#L422-L458","documentation":"testConnection arms a fixed 5-second setTimeout that calls finishTest(false, timeout-message) if the ioredis client has not reached ready + PING by then; cleanupTestClient then disconnects the still-pending attempt. A timeout (rather than a fast rejection) means packets are being silently dropped or the SSH/TLS handshake is slower than the fixed 5000ms budget.","triggerScenarios":"Firewall/security group dropping SYN packets to the port (no RST, so no ECONNREFUSED), unroutable host (wrong VPC/VPN), DNS resolution hang, slow SSH tunnel establishment, or a TLS handshake to a dead endpoint - any case where neither 'ready' nor 'error' fires within 5000ms.","commonSituations":"Cloud security groups not allowing the client IP, VPN down while connecting to internal Redis, high-latency SSH bastion hops, NAT without port forwarding.","solutions":["Check the firewall/security group allows the client to reach the port (telnet host port / tcping)","Verify the VPN/network path and DNS resolution from this machine","Retry once - transient network hiccups are a common cause","If the path is legitimately slow (multi-hop SSH, high-latency TLS), raise the 5000ms budget in testConnection's testTimer"],"exampleFix":"// before\nthis.testTimer = setTimeout(() => {\n  this.finishTest(false, this.$t('message.test_connection_timeout'));\n}, 5000);\n\n// after - budget scales with SSH/TLS overhead\nconst budget = config.sshOptions || config.sslOptions ? 15000 : 5000;\nthis.testTimer = setTimeout(() => {\n  this.finishTest(false, this.$t('message.test_connection_timeout'));\n}, budget);","handlingStrategy":"retry","validationCode":"// distinguish 'slow' from 'unreachable' before the 5s test:\n// a TCP probe that also times out means dropped packets, not a slow handshake\nconst reachable = await tcpReachable(host, port, 3000);\nif (!reachable) {\n  showError('host unreachable - check firewall/security group');\n  return;\n}","typeGuard":null,"tryCatchPattern":"// race the connection against a timer, and retry transient timeouts once\nawait Promise.race([\n  connectWithPing(config),\n  new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), 5000)),\n]).catch(async (e) => {\n  if (e.message === 'timeout' && !(await retryOnce())) {\n    showError('connection timeout - likely firewall or routing');\n  }\n});","preventionTips":["Silent timeout vs fast refusal: refusal means wrong port/host; timeout usually means firewall drop","Keep the timeout budget proportional to the path (SSH bastion + TLS needs more than 5s)","Clean up the pending client when a timeout fires (cleanupTestClient) or it leaks sockets"],"tags":["redis","ioredis","timeout","network","firewall","ardm"],"backgroundTag":"connection-timeout","analyzedSha":"c149855106628babcdfb7675a8e7ba9434d2492a","analyzedAt":"2026-08-22T09:06:28.613Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}