janhq/jan · error

error.message

Error message

error.message

What it means

The MLX server can send SSE lines of the form 'error: {json}'; the extension parses the JSON and rethrows its message field verbatim. This is a pass-through of a server-side streaming error, so the text varies (load failure, generation error, out-of-memory, etc.).

Solutions

  1. Read the propagated message for the concrete server-side cause
  2. Check MLX server logs/stderr at the time of the failure
  3. Verify model files are intact (re-download if corrupted)
  4. Update server and extension to matching versions
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

const isSseErrorLine = (line) => line.startsWith('error: ') && (() => { try { return typeof JSON.parse(line.slice(7))?.message === 'string' } catch { return false } })()

Try / catch

try {
  for await (const chunk of streamChat(messages, model)) handle(chunk)
} catch (e) {
  logger.error('MLX stream error:', e.message)
  await reloadModel(model.id) // server-side failure: safest recovery is reload
  throw e
}

Prevention

When it happens

Trigger: During handleStreamingResponse, a streamed line starts with 'error: ' and its JSON contains {message: ...} — the server failed during generation (e.g. model error, memory exhaustion, invalid request detected mid-stream).

Common situations: MLX server hitting memory limits while generating, corrupted model weights, incompatibilities between server and extension streaming protocol versions.

Related errors


AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17). Data as JSON: /api/errors/9391f8eb1a95e5c4. Report an issue: GitHub.

Appendix: source

Thrown at extensions/mlx-extension/src/index.ts:524

          if (trimmedLine.startsWith('data: ')) {
            const jsonStr = trimmedLine.slice(6)
            try {
              const data = JSON.parse(jsonStr) as chatCompletionChunk

              if (data.choices?.[0]?.finish_reason === 'length') {
                throw new Error(OUT_OF_CONTEXT_SIZE)
              }

              yield data
            } catch (e) {
              logger.error('Error parsing MLX stream JSON:', e)
              throw e
            }
          } else if (trimmedLine.startsWith('error: ')) {
            const jsonStr = trimmedLine.slice(7)
            const error = JSON.parse(jsonStr)
            throw new Error(error.message)
          }
        }
      }
    } finally {
      reader.releaseLock()
    }
  }

  override async delete(modelId: string): Promise<void> {
    const modelDir = await joinPath([
      await this.getProviderPath(),
      'models',
      modelId,
    ])

    const modelConfigPath = await joinPath([modelDir, 'model.yml'])
    if (!(await fs.existsSync(modelConfigPath))) {
      throw new Error(`Model ${modelId} does not exist`)

View on GitHub (pinned to 7205d770c1)