janhq/jan · error

Model already loaded!!

Error message

Model already loaded!!

What it means

load() first checks findSessionByModel(modelId); if a live session for that model already exists it throws 'Model already loaded!!'. Loading the same model twice is not permitted — the extension manages one session per model, and loadModelId checks come before the concurrent-load dedup via loadingModels map.

Solutions

  1. Check findSessionByModel / session state and reuse the existing sessionInfo instead of loading again
  2. Call unload(modelId) before loading if you need a fresh load
  3. Serialize load requests in your UI so a second click is ignored while loading
  4. Wrap the load in a guard: if already loaded, return the existing session

Example fix

// before
const s = await load(modelId) // may double-load
// after
let s = await findSessionByModel(modelId)
if (!s) s = await load(modelId)
Defensive patterns

Strategy: try-catch

Validate before calling

const existing = await findSessionByModel(modelId)
if (existing) return existing // already loaded; reuse

Try / catch

try {
  return await load(modelId)
} catch (e) {
  if (e.message === 'Model already loaded!!') return await findSessionByModel(modelId)
  throw e
}

Prevention

When it happens

Trigger: Calling load() (or the public loadModel path) twice for the same modelId without unloading in between; UI double-clicking the load button; a retry loop after a slow load that actually succeeded.

Common situations: Race between user action and an automatic preload; re-running a script that loads models without unloading; a previous load completed but the caller assumed it failed.

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/fe53391a59e47dca. Report an issue: GitHub.

Appendix: source

Thrown at extensions/llamacpp-extension/src/index.ts:2258

        if (
          cleanKey &&
          valueParts.length > 0 &&
          !cleanKey.startsWith('LLAMA')
        ) {
          target[cleanKey] = valueParts.join('=').trim()
        }
      })
  }

  override async load(
    modelId: string,
    _settings?: unknown,
    isEmbedding: 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, isEmbedding)
    this.loadingModels.set(modelId, loadingPromise)

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

  // Awaits the deferred startup, then makes one direct attempt if the worker
  // still isn't up. Safe to call redundantly: start_engine returns the running

View on GitHub (pinned to 7205d770c1)