{"record":{"id":"7e61adca1554a66d","repo":"janhq/jan","slug":"mlx-api-request-failed-with-status-response-stat","errorCode":null,"errorMessage":"MLX API request failed with status ${response.status}: ${JSON.stringify(errorData)}","messagePattern":"MLX API request failed with status (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"extensions/mlx-extension/src/index.ts","lineNumber":403,"sourceCode":"      'Authorization': `Bearer ${sessionInfo.api_key}`,\n    }\n\n    const body = JSON.stringify(opts)\n\n    if (opts.stream) {\n      return this.handleStreamingResponse(url, headers, body, abortController)\n    }\n\n    const response = await fetch(url, {\n      method: 'POST',\n      headers,\n      body,\n      signal: abortController?.signal,\n    })\n\n    if (!response.ok) {\n      const errorData = await response.json().catch(() => null)\n      throw new Error(\n        `MLX API request failed with status ${response.status}: ${JSON.stringify(errorData)}`\n      )\n    }\n\n    const completionResponse = (await response.json()) as chatCompletion\n\n    if (completionResponse.choices?.[0]?.finish_reason === 'length') {\n      throw new Error(OUT_OF_CONTEXT_SIZE)\n    }\n\n    return completionResponse\n  }\n\n  private async *handleStreamingResponse(\n    url: string,\n    headers: HeadersInit,\n    body: string,\n    abortController?: AbortController","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/extensions/mlx-extension/src/index.ts#L385-L421","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif (!response.ok) {\n  const errorData = await response.json().catch(() => null)\n  throw new Error(`MLX API request failed with status ${response.status}: ${JSON.stringify(errorData)}`)\n}\n\n// after\nif (!response.ok) {\n  const errorData = await response.json().catch(() => null)\n  throw new Error(`MLX chat ${response.status}: ${errorData?.error?.message ?? JSON.stringify(errorData)}`)\n}","handlingStrategy":"try-catch","validationCode":"import { z } from 'zod'\nconst ChatReq = z.object({\n  model: z.string(),\n  messages: z.array(z.object({ role: z.string(), content: z.any() })),\n  max_tokens: z.number().optional(),\n})\nconst safe = ChatReq.parse(opts) // strip unknown fields before send","typeGuard":null,"tryCatchPattern":"try {\n  return await engine.chat(opts, abort)\n} catch (e) {\n  const msg = String(e)\n  if (/status 4\\d\\d/.test(msg)) {\n    // client-side error: fix opts and retry, don't loop\n    throw new Error(`Chat rejected: ${msg}`)\n  }\n  throw e\n}","preventionTips":["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."],"tags":["http","chat","api-error","mlx","typescript"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}