janhq/jan · error · Error

No running MLX session found for model: ${modelId}

Error message

No running MLX session found for model: ${modelId}

What it means

Thrown by createMlxModel when invoke('plugin:mlx|find_mlx_session_by_model', { modelId }) returns null after the start phase. Mirrors the llama.cpp noRunningSession case but, unlike [143], uses a hardcoded English string instead of an i18n key — an inconsistency to be aware of when localizing (model-factory.ts:1022).

Source

Thrown at web-app/src/lib/model-factory.ts:1022

        }
      } catch (error) {
        console.error('Failed to start MLX model:', error)
        throw new Error(
          i18n.t('model-errors:startModelFailed', {
            reason: describeEngineError(error),
          })
        )
      }
    }

    // Get session info which includes port and api_key
    const sessionInfo = await invoke<SessionInfo | null>(
      'plugin:mlx|find_mlx_session_by_model',
      { modelId }
    )

    if (!sessionInfo) {
      throw new Error(`No running MLX session found for model: ${modelId}`)
    }

    const baseUrl = `http://localhost:${sessionInfo.port}`
    const authHeaders = {
      Authorization: `Bearer ${sessionInfo.api_key}`,
      Origin: 'tauri://localhost',
    }

    // Share the common fetch (param normalisation + error-body cleaning that
    // rebuilds upstream errors from buffered text rather than re-decoding the
    // raw stream) with every other provider, then layer MLX's /cancel-on-abort
    // on top.
    let baseCustomFetch = createCustomFetch(
      httpFetch,
      parameters,
      false,
      undefined,
      true

View on GitHub (pinned to fad3f12a14)

Solutions

  1. Ensure provider is passed so startModel runs before the session lookup.
  2. Avoid model swaps and page reloads during MLX boot.
  3. Inspect the mlx extension logs for a crashed/unregistered session.
  4. Align modelId between startModel and find_mlx_session_by_model.

Example fix

// before
if (!sessionInfo) {
  throw new Error(`No running MLX session found for model: ${modelId}`)
}
// after: use the i18n key like the llama.cpp path for consistency
if (!sessionInfo) {
  throw new Error(i18n.t('model-errors:noRunningSession', { model: modelId }))
}
Defensive patterns

Strategy: retry

Validate before calling

function assertProviderForMlx(provider: ProviderObject | undefined, modelId: string) {
  if (!provider) throw new Error(`Cannot start MLX ${modelId}: provider object is required`)
}

Type guard

function isSessionInfo(x: unknown): x is SessionInfo {
  return typeof x === 'object' && x !== null && typeof (x as SessionInfo).port === 'number'
}

Try / catch

let sessionInfo = await invoke<SessionInfo | null>('plugin:mlx|find_mlx_session_by_model', { modelId })
if (!sessionInfo) {
  await new Promise(r => setTimeout(r, 500))
  sessionInfo = await invoke<SessionInfo | null>('plugin:mlx|find_mlx_session_by_model', { modelId })
}
if (!sessionInfo) throw new Error(i18n.t('model-errors:noRunningSession', { model: modelId }))

Prevention

When it happens

Trigger: provider is falsy so the startModel block is skipped; startModel resolved but the MLX sidecar session was not registered or crashed between start and lookup; rapid model switching / page reload during boot; KILL_SIDECAR emitted mid-start.

Common situations: Switching away from the MLX model immediately after selecting it; MLX sidecar crashed on init but startModel's promise already resolved; modelId mismatch between start and lookup.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/5530948fcdece88d. Report an issue: GitHub.