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
- Verify the provider Base URL is correct and the server is running (curl the endpoint).
- For local servers: start llama.cpp/the engine before sending.
- For TLS errors: install/trust the certificate or use the correct HTTPS endpoint.
- For timeouts: increase the provider timeout or reduce model size for faster first-token.
- 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
- Verify the provider Base URL and that the server is running before sending.
- For local servers, ensure the engine is started.
- Trust self-signed certs in the app config or use valid HTTPS.
- Increase provider timeout for slow first-token responses.
- Check DNS/proxy egress to the provider hostname.
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
- ServiceHub not initialized or model/provider missing.
- model-errors:createModelFailed
- Failed to fetch models from ${provider.provider}: ${result.s
- Authentication failed: API key is required or invalid for ${
- Models endpoint not found for ${provider.provider}. Check th
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/e89d75d32a6aeffe.
Report an issue: GitHub.