janhq/jan · error · Error

${friendly} (${requestUrlOf(input)})

Error message

${friendly} (${requestUrlOf(input)})

What it means

Thrown by the custom `fetch` wrapper in model-factory when `baseFetch(input, init)` rejects with a transport-class error (DNS, timeout, TLS, connection refused/reset). `describeTransportError` classifies the low-level message into a friendly string; if it returns non-null, the error is re-thrown as `${friendly} (${requestUrlOf(input)})`. Non-transport errors (e.g. programming errors) are re-thrown untouched.

Source

Thrown at web-app/src/lib/model-factory.ts:465

    let rawBody: Record<string, unknown> | null = null
    if (init?.method === 'POST' || !init?.method) {
      try {
        rawBody = init?.body ? JSON.parse(init.body as string) : {}
      } catch (e) {
        throw new Error(
          `Failed to parse request body as JSON: ${e instanceof Error ? e.message : String(e)}`
        )
      }
      init = { ...init, body: JSON.stringify(buildBody(rawBody!, true)) }
    }

    let res: Response
    try {
      res = await baseFetch(input, init)
    } catch (err) {
      const friendly = describeTransportError(err)
      if (!friendly) throw err
      throw new Error(`${friendly} (${requestUrlOf(input)})`)
    }
    if (res.ok) {
      // OpenAI-compatible servers may interleave custom named SSE events (e.g.
      // tool-progress) with chat.completion.chunk data; the AI SDK validates
      // every data line against the chunk schema, so strip non-default events.
      // Opt-in only: Anthropic and the OpenAI Responses API use named SSE
      // events as their protocol, so filtering there blanks the whole stream.
      const contentType = res.headers.get('content-type') || ''
      if (
        filterNamedSseEvents &&
        res.body &&
        contentType.includes('text/event-stream')
      ) {
        return new Response(filterDefaultSseEvents(res.body), {
          status: res.status,
          statusText: res.statusText,
          headers: res.headers,
        })

View on GitHub (pinned to fad3f12a14)

Solutions

  1. Verify the provider Base URL is correct and the server is running (curl the endpoint).
  2. For local servers: start llama.cpp/the engine before sending.
  3. For TLS errors: install/trust the certificate or use the correct HTTPS endpoint.
  4. For timeouts: increase the provider timeout or reduce model size for faster first-token.
  5. Check DNS/proxy egress to the provider hostname.

Example fix

// before
} catch (err) {
  const friendly = describeTransportError(err)
  if (!friendly) throw err
  throw new Error(`${friendly} (${requestUrlOf(input)})`)
}

// after
} catch (err) {
  const friendly = describeTransportError(err)
  if (!friendly) throw err
  console.error('[transport] request to', requestUrlOf(input), 'failed:', err)
  throw new Error(`${friendly} (${requestUrlOf(input)})`)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate provider reachability before the first real request.
async function isProviderReachable(baseUrl: string): Promise<boolean> {
  try {
    const u = new URL(baseUrl)
    return u.protocol === 'http:' || u.protocol === 'https:'
  } catch {
    return false
  }
}

Type guard

function isTransportError(err: unknown): boolean {
  const raw = err instanceof Error ? err.message : String(err)
  return /error sending request|failed to fetch|networkerror|connection (refused|reset|closed)|timed out|tls|certificate|dns/i.test(raw)
}

Try / catch

try {
  res = await baseFetch(input, init)
} catch (err) {
  const friendly = describeTransportError(err)
  if (!friendly) throw err // non-transport — let it propagate
  console.error('[transport]', requestUrlOf(input), err)
  throw new Error(`${friendly} (${requestUrlOf(input)})`)
}

Prevention

When it happens

Trigger: Any chat-completion / model request where the provider endpoint is unreachable: DNS resolution failure for the provider Base URL; connection refused (server down); TLS/certificate mismatch; request timeout; broken pipe mid-stream. The wrapper catches the fetch rejection and attaches the request URL for debuggability.

Common situations: Wrong/mistyped Base URL in provider settings; local llama.cpp server not running (connection refused); self-signed cert without trust store config; corporate proxy; provider outage; intermittent network drop mid-generation.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/e89d75d32a6aeffe. Report an issue: GitHub.