{"record":{"id":"c9d43e7e19770818","repo":"PaddlePaddle/PaddleOCR","slug":"connection-failed-message","errorCode":null,"errorMessage":"Connection failed: ${message}","messagePattern":"Connection failed: (.+?)","errorType":"exception","errorClass":"NetworkError","httpStatus":null,"severity":"error","filePath":"api_sdk/typescript/src/internal/http.ts","lineNumber":221,"sourceCode":"      abort();\n    } else {\n      signal?.addEventListener(\"abort\", abort, { once: true });\n    }\n    try {\n      resp = await this.fetchImpl(url, {\n        ...init,\n        headers,\n        signal: abortController.signal,\n      });\n    } catch (e: unknown) {\n      if (signal?.aborted) {\n        throw userAbortReason(signal);\n      }\n      if (timeoutController.signal.aborted) {\n        throw new RequestTimeoutError(effectiveTimeout, { cause: e });\n      }\n      const message = e instanceof Error ? e.message : String(e);\n      throw new NetworkError(`Connection failed: ${message}`);\n    } finally {\n      clearTimeout(timeoutID);\n      signal?.removeEventListener(\"abort\", abort);\n    }\n\n    if (resp.ok) return resp;\n\n    let text = await resp.text();\n    try {\n      const payload = JSON.parse(text) as { msg?: string; message?: string; errorMsg?: string };\n      text = payload.msg || payload.message || payload.errorMsg || text;\n    } catch {\n      // Keep raw response text.\n    }\n    if (resp.status === 401 || resp.status === 403) {\n      throw new AuthError(`Authentication failed: ${text}`);\n    } else if (resp.status === 400) {\n      throw new InvalidRequestError(`Bad request: ${text}`);","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/api_sdk/typescript/src/internal/http.ts#L203-L239","documentation":"NetworkError with 'Connection failed: <message>' is the catch-all for fetch rejections that are neither a user abort nor a timeout: DNS resolution failure, TCP connection refused, TLS errors, or fetch runtime incompatibilities. The original error's message is embedded and the original error is attached as `cause`. No HTTP response was ever received.","triggerScenarios":"Any request when the API host cannot be reached: wrong/custom base URL with an unresolvable hostname, firewall or egress rules blocking the endpoint, self-signed certificate behind a corporate proxy, offline environment, or passing a fetchImpl that lacks required runtimes (e.g. undici vs Node version mismatch).","commonSituations":"CI containers without outbound internet; corporate TLS-inspecting proxies requiring custom CA bundles; air-gapped environments; typos in the configured endpoint; Node < 18 where global fetch is unavailable; IPv6-only networks misbehaving.","solutions":["Verify connectivity to the API host directly: curl -v https://<api-host>/ — if that fails, fix DNS/firewall/proxy first","Read e.cause for the real reason (ENOTFOUND, ECONNREFUSED, certificate errors) and address that specific failure","For corporate proxies, set HTTPS_PROXY/HTTP_PROXY or inject a proxy-aware Agent via the SDK's custom fetchImpl","Ensure Node.js >= 18 (built-in fetch) or supply a compatible fetchImpl"],"exampleFix":"try {\n  const jobs = await client.getBatchStatus(batchId);\n} catch (e) {\n  if (e instanceof NetworkError) {\n    console.error(\"underlying cause:\", e.cause); // e.g. ENOTFOUND\n    throw new Error(\"API unreachable — check network/proxy config\");\n  }\n}","handlingStrategy":"try-catch","validationCode":"async function canReach(host: string): Promise<boolean> {\n  try {\n    await fetch(`https://${host}`, { method: \"HEAD\" });\n    return true;\n  } catch {\n    return false;\n  }\n}","typeGuard":"function isNetworkError(e: unknown): e is NetworkError {\n  return e instanceof NetworkError;\n}","tryCatchPattern":"try {\n  const s = await poller.getStatus(jobId);\n} catch (e) {\n  if (e instanceof NetworkError) {\n    // inspect e.cause: ENOTFOUND -> DNS, ECONNREFUSED -> firewall, CERT_* -> proxy TLS\n    failFastWithDiagnostics(e.cause);\n  }\n  throw e;\n}","preventionTips":["Run a connectivity pre-flight (DNS + HEAD request) at app startup and fail fast with a clear message","Configure proxy agents explicitly in containerized/corporate environments","Require Node >= 18 or inject a fetchImpl so global fetch is guaranteed"],"tags":["network","dns","tls","typescript"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}