hcengineering/platform · error · NetworkError

Network error ${err}

Error message

Network error ${err}

What it means

fetchSafe wraps the global fetch call; when fetch itself rejects — DNS failure, connection refused/reset, TLS error, request aborted — it rethrows as a NetworkError with the original error interpolated into the message. Non-2xx HTTP responses are NOT this error; those become BillingError instead.

Source

Thrown at packages/billing-client/src/client.ts:118

    await fetchSafe(url, { method: 'POST', headers: { ...this.headers }, body })
  }

  async postAiTokensData (data: AiTokensData[]): Promise<void> {
    const path = '/api/v1/ai/tokens'
    const url = new URL(concatLink(this.endpoint, path))
    const body = JSON.stringify(data)

    await fetchSafe(url, { method: 'POST', headers: { ...this.headers }, body })
  }
}

async function fetchSafe (url: string | URL, init?: RequestInit): Promise<Response> {
  let response
  try {
    response = await fetch(url, init)
  } catch (err: any) {
    throw new NetworkError(`Network error ${err}`)
  }

  if (!response.ok) {
    const text = await response.text()
    throw new BillingError(text)
  }

  return response
}

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Verify the billing service is up and reachable: curl the billingUrl from the same host/container.
  2. Check the configured billing URL, port, and protocol (http vs https, DNS name).
  3. Inspect the inner error in the message (ENOTFOUND, ECONNREFUSED, certificate) to identify root cause.
  4. Add retry with backoff for transient outages around client calls.

Example fix

// before
const stats = await client.response(...) // Network error fetch failed
// after
const url = new URL(process.env.BILLING_URL!)
await dns.promises.lookup(url.hostname) // verify reachability first
const stats = await client.response(...)
Defensive patterns

Strategy: retry

Validate before calling

const url = new URL(billingUrl)
await dns.promises.lookup(url.hostname) // fail fast on unresolvable host before calling the client

Type guard

function isNetworkError(e: unknown): e is NetworkError {
  return e instanceof NetworkError
}

Try / catch

try {
  return await client.response(ws)
} catch (e) {
  if (e instanceof NetworkError) {
    await backoff(); return await client.response(ws) // retry transient connectivity failures
  }
  throw e
}

Prevention

When it happens

Trigger: Any BillingClient method that goes through fetchSafe (response, postLiveKitSessions, postLiveKitEgress, postAiTranscriptData, postAiTokensData) when the billing service is unreachable, the URL hostname is wrong, the port is closed, or TLS fails.

Common situations: Billing service down or redeploying; wrong billing URL/port in config; DNS not resolving in cluster/k8s; firewall or network policy blocking egress; self-signed certificate issues.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/88a3ed9b81cc7b82. Report an issue: GitHub.