janhq/jan · error · Error
MLX API request failed with status ${response.status}: ${JSO
Error message
MLX API request failed with status ${response.status}: ${JSON.stringify(errorData)} What it means
Thrown by chat() (non-streaming branch) when POST /v1/chat/completions returns non-OK. The JSON error body is captured (or null). Unlike the crash guards (errors 50/51), this means the request reached the server and was rejected — a 4xx/5xx with a real error payload.
Source
Thrown at extensions/mlx-extension/src/index.ts:403
'Authorization': `Bearer ${sessionInfo.api_key}`,
}
const body = JSON.stringify(opts)
if (opts.stream) {
return this.handleStreamingResponse(url, headers, body, abortController)
}
const response = await fetch(url, {
method: 'POST',
headers,
body,
signal: abortController?.signal,
})
if (!response.ok) {
const errorData = await response.json().catch(() => null)
throw new Error(
`MLX API request failed with status ${response.status}: ${JSON.stringify(errorData)}`
)
}
const completionResponse = (await response.json()) as chatCompletion
if (completionResponse.choices?.[0]?.finish_reason === 'length') {
throw new Error(OUT_OF_CONTEXT_SIZE)
}
return completionResponse
}
private async *handleStreamingResponse(
url: string,
headers: HeadersInit,
body: string,
abortController?: AbortControllerView on GitHub (pinned to fad3f12a14)
Solutions
- Read the embedded errorData — the server's message pinpoints the cause (bad template, unknown field, OOM).
- Strip non-standard fields from opts before sending; match the OpenAI chat completions schema.
- Verify sessionInfo.api_key matches the running session.
- For 5xx, check server logs; a chat-template error may require a different model build.
Example fix
// before
if (!response.ok) {
const errorData = await response.json().catch(() => null)
throw new Error(`MLX API request failed with status ${response.status}: ${JSON.stringify(errorData)}`)
}
// after
if (!response.ok) {
const errorData = await response.json().catch(() => null)
throw new Error(`MLX chat ${response.status}: ${errorData?.error?.message ?? JSON.stringify(errorData)}`)
} Defensive patterns
Strategy: try-catch
Validate before calling
import { z } from 'zod'
const ChatReq = z.object({
model: z.string(),
messages: z.array(z.object({ role: z.string(), content: z.any() })),
max_tokens: z.number().optional(),
})
const safe = ChatReq.parse(opts) // strip unknown fields before send Try / catch
try {
return await engine.chat(opts, abort)
} catch (e) {
const msg = String(e)
if (/status 4\d\d/.test(msg)) {
// client-side error: fix opts and retry, don't loop
throw new Error(`Chat rejected: ${msg}`)
}
throw e
} Prevention
- Send only OpenAI-schema fields in opts; strip custom keys.
- Confirm sessionInfo.api_key matches the running session.
- Validate tools/function_calling format against the model's template support.
When it happens
Trigger: Malformed chatCompletionRequest body the MLX server rejects (400); unknown model id (404); request payload exceeds server limits; server-side inference error (500) such as a bad chat template or tokenization failure; 401 from a wrong api_key.
Common situations: Custom request builder omits required fields; tools/functions format unsupported by the model's template; opts contains fields the MLX server doesn't recognize; api_key drift between session and request.
Related errors
- No active MLX session found for model: ${opts.model}
- MLX model appears to have crashed! Please reload!
- MLX model has crashed! Please reload!
- the request exceeds the available context size.
- Response body is null
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/7e61adca1554a66d.
Report an issue: GitHub.