janhq/jan · warning · Error
Model already loaded!
Error message
Model already loaded!
What it means
Thrown by load() when findSessionByModel(modelId) already returns a session, meaning the model is currently loaded and serving. Loading it again would start a second server process on a new port and double GPU memory use, so the extension refuses. A separate loadingModels map handles concurrent in-flight loads.
Source
Thrown at extensions/mlx-extension/src/index.ts:216
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 fad3f12a14)
Solutions
- Check engine.getLoadedModels()/findSessionByModel before calling load, and reuse the existing session.
- Call engine.unload(modelId) first if you genuinely need a fresh load with new settings.
- If the entry is stale (process actually dead), run unload to clear it, then load.
Example fix
// before
await engine.load(modelId, overrideSettings)
// after
const existing = await engine.findSessionByModel(modelId)
if (existing) {
// reuse, or unload first if overrideSettings require a reload
return existing
}
await engine.load(modelId, overrideSettings) Defensive patterns
Strategy: validation
Validate before calling
const existing = await engine.findSessionByModel(modelId).catch(() => null)
if (existing) {
// already loaded; reuse or unload first
return existing
}
await engine.load(modelId) Try / catch
try {
await engine.load(modelId, overrideSettings)
} catch (e) {
if (/Model already loaded/.test(String(e))) {
return // acceptable: nothing to do
}
throw e
} Prevention
- Check findSessionByModel/getLoadedModels before calling load.
- Debounce UI actions that trigger load to prevent races.
- Call unload before re-loading with new settings.
When it happens
Trigger: Calling engine.load(modelId) twice without an intervening unload(); a chat thread already loaded the model and a second UI action triggers another load; the session registry was not cleared after a crash so findSessionByModel returns a stale entry.
Common situations: Race between two 'start chat' actions; model auto-loaded on app start and a manual load is also issued; a previous crash left a zombie session entry that findSessionByModel still finds.
Related errors
- No active MLX session found for model: ${modelId}
- No active MLX session found for model: ${opts.model}
- MLX model appears to have crashed! Please reload!
- MLX model has crashed! Please reload!
- Model ${modelId} does not exist
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/c66a80bdb2cee336.
Report an issue: GitHub.