janhq/jan · error

Model already loaded!

Error message

Model already loaded!

What it means

load() first checks findSessionByModel; if a session for that modelId already exists it throws 'Model already loaded!' instead of starting a duplicate server process. This is a deliberate guard against double-loading the same MLX model.

Solutions

  1. Check whether the model is loaded first (findSessionByModel/sessionInfo) and reuse the existing session instead of calling load
  2. Unload the existing session (unload(modelId)) before loading again if a fresh load is required
  3. If the session is stale (process actually dead), clear stale session state/restart the app then retry
  4. Guard call sites so load is only invoked when not already loaded/loading

Example fix

// before
await mlx.load(modelId)
// after
const existing = await mlx.getSessionInfo(modelId)
const session = existing ?? (await mlx.load(modelId))
Defensive patterns

Strategy: try-catch

Validate before calling

// Check before load
const existing = await mlx.getSessionInfo(modelId)
if (existing) throw new Error(`${modelId} already loaded; reuse it`)

Try / catch

try {
  await mlx.load(modelId)
} catch (e) {
  if (!String(e).includes('Model already loaded')) throw e
  // reuse existing session
}

Prevention

When it happens

Trigger: Calling load(modelId) when the model is already running — e.g. clicking Load twice, loading from two UI surfaces, or a previous session that never unloaded (stale session record).

Common situations: Double-clicking load buttons, race between UI state and backend state after a crash that left a session record, or re-running a script that loads models without unloading first.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

  private async getRandomPort(): Promise<number> {
    try {
      return await invoke<number>('plugin:mlx|get_mlx_random_port')
    } catch {
      logger.error('Unable to find a suitable port for MLX server')
      throw new Error('Unable to find a suitable port for MLX model')
    }
  }

  override async load(
    modelId: string,
    overrideSettings?: any,
    isEmbedding: boolean = false,
    bypassAutoUnload: boolean = false
  ): Promise<SessionInfo> {
    const sInfo = await this.findSessionByModel(modelId)
    if (sInfo) {
      throw new Error('Model already loaded!')
    }

    if (this.loadingModels.has(modelId)) {
      return this.loadingModels.get(modelId)!
    }

    const loadingPromise = this.performLoad(
      modelId,
      overrideSettings,
      isEmbedding,
      bypassAutoUnload
    )
    this.loadingModels.set(modelId, loadingPromise)

    try {
      return await loadingPromise
    } finally {
      this.loadingModels.delete(modelId)

View on GitHub (pinned to 7205d770c1)