{"record":{"id":"8b110ccc45acf5c3","repo":"docmirror/dev-sidecar","slug":"speed-test-by-tcp-error","errorCode":null,"errorMessage":"[speed] test by TCP error:  ","messagePattern":"\\[speed\\] test by TCP error:  ","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/mitmproxy/src/lib/speed/SpeedTester.js","lineNumber":250,"sourceCode":"      const startTime = Date.now()\n\n      let isOver = false\n      const timeout = 5000\n      let timeoutId = null\n\n      const client = net.createConnection({ host, port: this.port, family: host.includes(':') ? 6 : 4 }, () => {\n        isOver = true\n        clearTimeout(timeoutId)\n\n        const connectionTime = Date.now()\n        resolve({ status: 'success', by: 'TCP', target: `${host}:${this.port}`, time: connectionTime - startTime })\n        client.end()\n      })\n      client.on('error', (e) => {\n        isOver = true\n        clearTimeout(timeoutId)\n\n        log.warn('[speed] test by TCP error:  ', this.hostname, `➜ ${host}:${this.port} from DNS '${dns}', cost: ${Date.now() - startTime} ms, errorMsg:`, e.message)\n        reject(e)\n        client.destroy()\n      })\n\n      timeoutId = setTimeout(() => {\n        if (!isOver) {\n          isOver = true\n          log.warn('[speed] test by TCP timeout:', this.hostname, `➜ ${host}:${this.port} from DNS '${dns}', cost: ${Date.now() - startTime} ms`)\n          reject(new Error('timeout'))\n          client.destroy()\n        }\n      }, timeout)\n    })\n  }\n\n  // 暂不使用\n  // testByPing (item) {\n  //   return new Promise((resolve, reject) => {","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/docmirror/dev-sidecar/blob/7710cd56cce760c708f30b01d2d4056eb8c402d5/packages/mitmproxy/src/lib/speed/SpeedTester.js#L232-L268","documentation":"testByTCP rejects and logs a warning when the raw TCP probe socket to a candidate IP emits an 'error' event. The probe measures connect latency to host:port using the given DNS; any socket error (refused, unreachable, reset) rejects the promise, marking that candidate unusable for IP selection.","triggerScenarios":"Called from testOne for each backup IP: the TCP connect fails with ECONNREFUSED, EHOSTUNREACH, ENETUNREACH, ECONNRESET or similar before/instead of the timeout firing. The log includes cost in ms and the underlying error message.","commonSituations":"Testing candidate IPs where the service no longer listens (stale IP lists), blocked routes (common for github/docker IPs on some ISPs), or IPv6 addresses attempted on IPv4-only networks.","solutions":["Read the specific errno in the log to identify cause: ECONNREFUSED = IP dead, EHOSTUNREACH = route blocked","Update the candidate IP list (dns/providers / preSetIp config) with current working IPs for the domain","Disable IPv6 candidates if the local network is IPv4-only","No action needed if at least one candidate passes — the tester selects the best available IP"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const net = require('net')\nfunction tcpReachable(host, port, timeout = 3000) {\n  return new Promise(resolve => {\n    const s = net.connect(port, host)\n    s.setTimeout(timeout)\n    s.once('connect', () => { s.destroy(); resolve(true) })\n    s.once('error', () => resolve(false))\n    s.once('timeout', () => { s.destroy(); resolve(false) })\n  })\n}\n// pre-screen candidates before handing them to the tester","typeGuard":null,"tryCatchPattern":"try {\n  await tester.testByTCP(item)\n} catch (e) {\n  if (['ECONNREFUSED','EHOSTUNREACH','ENETUNREACH'].includes(e.code)) {\n    dropCandidate(item.host)\n  }\n}","preventionTips":["Pre-screen candidate IPs with a lightweight TCP check before speed testing","Remove IPv6 candidates on IPv4-only networks","Update IP source lists when a provider/CDN changes address ranges","Accept single-candidate failures — selection only needs one reachable backup"],"tags":["tcp","network","speed-test"],"backgroundTag":"tcp-connect-failed","analyzedSha":"7710cd56cce760c708f30b01d2d4056eb8c402d5","analyzedAt":"2026-08-31T22:07:07.234Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}