{"record":{"id":"b6d7be40fb304f29","repo":"hcengineering/platform","slug":"network-error-err-b6d7be","errorCode":null,"errorMessage":"Network error ${err}","messagePattern":"Network error (.+?)","errorType":"exception","errorClass":"NetworkError","httpStatus":null,"severity":"critical","filePath":"foundations/server/packages/datalake/src/client.ts","lineNumber":532,"sourceCode":"\n      while (buffer.length >= chunkSize) {\n        yield buffer.subarray(0, chunkSize)\n        buffer = buffer.subarray(chunkSize)\n      }\n    }\n    if (buffer.length > 0) {\n      yield buffer\n    }\n  }\n}\n\nasync function fetchSafe (ctx: MeasureContext, url: string | URL, init?: RequestInit): Promise<Response> {\n  let response\n  try {\n    response = await ctx.with('fetch', {}, () => fetch(url, init), { url: url.toString() }, { span: 'disable' })\n  } catch (err: any) {\n    ctx.error('network error', { err })\n    throw new NetworkError(`Network error ${err}`)\n  }\n\n  if (!response.ok) {\n    const text = await response.text()\n    if (response.status === 404) {\n      throw new NotFoundError(text)\n    } else {\n      throw new DatalakeError(text)\n    }\n  }\n\n  return response\n}\n","sourceCodeStart":514,"sourceCodeEnd":546,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/server/packages/datalake/src/client.ts#L514-L546","documentation":"NetworkError thrown by fetchSafe when the underlying fetch call itself rejects - the request never got an HTTP response. The original error is logged via ctx.error and embedded in the message. This is a transport-level failure, distinct from HTTP error statuses which produce NotFoundError or DatalakeError.","triggerScenarios":"Any client call routed through fetchSafe (response, getObject, getPartialObject, statObject, deleteObject, uploadFromS3) where fetch rejects: DNS failure, connection refused, TLS handshake error, aborted request, or socket timeout.","commonSituations":"Wrong endpoint/port in datalake config; datalake service down or unreachable from the container; self-signed cert failing TLS; VPN/firewall blocking; DNS resolution issues.","solutions":["Check the wrapped err (in message and ctx.error log) for ECONNREFUSED/ENOTFOUND/CERT codes.","Verify the datalake endpoint URL and port in configuration (this.endpoint).","Confirm the service is running and reachable (curl the endpoint).","Add retry with backoff for transient failures (the service layer's retry() covers get paths).","Fix TLS trust settings (NODE_EXTRA_CA_CERTS) if the error is certificate-related."],"exampleFix":"// before\nconst client = new DatalakeClient('http://datalake-wrong-host:9000', token)\n// after\nconst client = new DatalakeClient(process.env.DATALAKE_ENDPOINT ?? 'http://datalake:9000', token)","handlingStrategy":"retry","validationCode":"// preflight connectivity check\nconst reachable = await fetch(datalakeEndpoint, { method: 'HEAD' }).then(() => true).catch(() => false)\nif (!reachable) throw new Error(`Datalake endpoint unreachable: ${datalakeEndpoint}`)","typeGuard":"const isNetworkError = (e: unknown): e is NetworkError => e instanceof NetworkError","tryCatchPattern":"try {\n  await client.statObject(ctx, ws, name)\n} catch (err) {\n  if (err instanceof NetworkError) {\n    await sleep(backoff)\n    return client.statObject(ctx, ws, name) // retry transient transport failures\n  }\n  throw err\n}","preventionTips":["Externalize the datalake endpoint via env vars and validate at startup.","Health-check the service before batch operations.","Add retry-with-backoff around all client calls.","Set NODE_EXTRA_CA_CERTS for private CA environments."],"tags":["network","fetch","connectivity"],"backgroundTag":"fetch-network-error","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}