{"record":{"id":"72b0f0597b856b4e","repo":"ruvnet/ruflo","slug":"network","errorCode":"network","errorMessage":"network error: ${e instanceof Error ? e.message : String(e)}","messagePattern":"network error: (.+?)","errorType":"exception","errorClass":"OAuthError","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/security/src/oauth/client.ts","lineNumber":101,"sourceCode":"      body.error,\n      body.error_description,\n    );\n  } catch (e) {\n    if (e instanceof OAuthError) throw e;\n    throw new OAuthError('unexpected response shape from the server', 'unexpected_shape');\n  }\n}\n\nasync function postForm(path: string, form: Record<string, string>, base = authBaseUrl()): Promise<TokenResponse> {\n  let resp: Response;\n  try {\n    resp = await fetch(`${base}${path}`, {\n      method: 'POST',\n      headers: { 'content-type': 'application/x-www-form-urlencoded' },\n      body: new URLSearchParams(form).toString(),\n    });\n  } catch (e) {\n    throw new OAuthError(`network error: ${e instanceof Error ? e.message : String(e)}`, 'network');\n  }\n  return parseTokenResponse(resp);\n}\n\n/** `POST /oauth/token` with `grant_type=authorization_code`. */\nexport async function exchangeCode(\n  code: string,\n  codeVerifier: string,\n  redirectUri: string,\n  base = authBaseUrl(),\n): Promise<TokenResponse> {\n  return postForm(\n    '/oauth/token',\n    { grant_type: 'authorization_code', code, code_verifier: codeVerifier, client_id: CLIENT_ID, redirect_uri: redirectUri },\n    base,\n  );\n}\n","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/security/src/oauth/client.ts#L83-L119","documentation":"postForm wraps fetch for POST /oauth/token; any thrown fetch exception (DNS failure, ECONNREFUSED, TLS error, proxy refusal) is normalized to OAuthError code 'network' carrying the underlying message. The request never got an HTTP response — this is transport-level failure, not an OAuth decision.","triggerScenarios":"No DNS/route to auth.cognitum.one (offline sandbox); corporate network requiring HTTPS_PROXY that isn't set; COGNITUM_AUTH_URL pointing at an internal host with a self-signed cert Node doesn't trust; IPv6-only resolution breakage.","commonSituations":"CI jobs with no egress; forgotten proxy env vars on dev machines; private CAs missing from the Node trust store; transient DNS flakes on cloud runners.","solutions":["Check reachability: curl -v https://auth.cognitum.one/oauth/token — any HTTP status (even 4xx) means transport is fine","Set HTTPS_PROXY/HTTP_PROXY (and NO_PROXY where needed) on proxied networks","For private CAs: export NODE_EXTRA_CA_CERTS=/path/to/ca.pem","Retry with backoff — transport failures are frequently transient"],"exampleFix":"# before: CI runner with no direct egress\n# → network error: fetch failed\n\n# after\nexport HTTPS_PROXY=http://proxy.corp:3128\nexport NO_PROXY=localhost,127.0.0.1","handlingStrategy":"retry","validationCode":"async function authHostReachable(base: string): Promise<boolean> {\n  try {\n    await fetch(base, { method: 'HEAD' });\n    return true; // any response means transport works\n  } catch {\n    return false;\n  }\n}\nif (!(await authHostReachable(process.env.COGNITUM_AUTH_URL ?? 'https://auth.cognitum.one'))) {\n  throw new Error('auth host unreachable — check network/proxy config');\n}","typeGuard":"function isOAuthNetworkError(e: unknown): boolean {\n  return e instanceof Error && e.name === 'OAuthError' && (e as { code?: string }).code === 'network';\n}","tryCatchPattern":"for (let attempt = 1; attempt <= 3; attempt++) {\n  try {\n    return await exchangeCode(code, verifier, redirectUri);\n  } catch (e) {\n    if (isOAuthNetworkError(e) && attempt < 3) {\n      await new Promise((r) => setTimeout(r, 500 * 2 ** attempt));\n      continue;\n    }\n    throw e;\n  }\n}","preventionTips":["Configure HTTPS_PROXY/NO_PROXY explicitly in restricted network environments","Set NODE_EXTRA_CA_CERTS for private CAs instead of disabling TLS verification","Wrap token requests in bounded retry with backoff — but never retry non-idempotent code exchanges without exactly-once protection"],"tags":["oauth","network","dns","proxy","tls"],"backgroundTag":"network-request-failed","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}