janhq/jan · error · Error
MLX model appears to have crashed! Please reload!
Error message
MLX model appears to have crashed! Please reload!
What it means
Thrown by chat() when the MLX process is reported alive (is_mlx_process_running) but the GET /health fetch throws. The process exists yet its HTTP server is not responding — it is wedged, still initializing, or the health endpoint is unreachable. The extension unloads the model first, then throws so the caller reloads.
Source
Thrown at extensions/mlx-extension/src/index.ts:375
opts: chatCompletionRequest,
abortController?: AbortController
): Promise<chatCompletion | AsyncIterable<chatCompletionChunk>> {
const sessionInfo = await this.findSessionByModel(opts.model)
if (!sessionInfo) {
throw new Error(`No active MLX session found for model: ${opts.model}`)
}
// Check if the process is alive
const isAlive = await invoke<boolean>('plugin:mlx|is_mlx_process_running', {
pid: sessionInfo.pid,
})
if (isAlive) {
try {
await fetch(`http://localhost:${sessionInfo.port}/health`)
} catch (e) {
this.unload(sessionInfo.model_id)
throw new Error('MLX model appears to have crashed! Please reload!')
}
} else {
throw new Error('MLX model has crashed! Please reload!')
}
const baseUrl = `http://localhost:${sessionInfo.port}/v1`
const url = `${baseUrl}/chat/completions`
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${sessionInfo.api_key}`,
}
const body = JSON.stringify(opts)
if (opts.stream) {
return this.handleStreamingResponse(url, headers, body, abortController)
}
View on GitHub (pinned to fad3f12a14)
Solutions
- Retry chat() after a brief wait; the server may finish booting (the extension already unloaded, so reload first).
- Increase the load timeout / readiness wait so /health is live before chat is allowed.
- On persistent failure, fully reload the model via load() to spawn a fresh server process.
- Check GPU/system resources — a wedged server often follows memory pressure.
Example fix
// before
const completion = await engine.chat(opts)
// after
try {
return await engine.chat(opts)
} catch (e) {
if (/appears to have crashed/.test(String(e))) {
await engine.load(opts.model) // reload then retry once
return await engine.chat(opts)
}
throw e
} Defensive patterns
Strategy: retry
Validate before calling
async function mlxHealthReady(port: number): Promise<boolean> {
try { return (await fetch(`http://localhost:${port}/health`)).ok }
catch { return false }
}
if (!(await mlxHealthReady(sessionInfo.port))) {
throw new Error('MLX /health not ready; wait or reload')
} Try / catch
try {
return await engine.chat(opts, abort)
} catch (e) {
if (/appears to have crashed/.test(String(e))) {
await engine.load(opts.model) // extension already unloaded it
return await engine.chat(opts, abort)
}
throw e
} Prevention
- Wait for /health 200 after load() before issuing chat.
- Increase the load/readiness timeout so the server is ready before chat.
- Watch GPU/memory pressure that wedges the server.
When it happens
Trigger: MLX server process is up but still binding its port or initializing weights when /health is hit; the server hung after a GPU error but did not exit; port mismatch where the recorded port no longer belongs to the server; localhost resolution issue.
Common situations: chat() called immediately after load() returned but before the HTTP server was truly ready; transient Metal/GPU fault wedged the server; firewall blocks localhost loopback on the chosen port.
Related errors
- MLX model has crashed! Please reload!
- No active MLX session found for model: ${opts.model}
- Model already loaded!
- No active MLX session found for model: ${modelId}
- MLX API request failed with status ${response.status}: ${JSO
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/4820bd60fe15f7f3.
Report an issue: GitHub.