{"record":{"id":"7232227f65ec0537","repo":"janhq/jan","slug":"no-active-mlx-session-found-for-model-modelid","errorCode":null,"errorMessage":"No active MLX session found for model: ${modelId}","messagePattern":"No active MLX session found for model: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"extensions/mlx-extension/src/index.ts","lineNumber":325,"sourceCode":"        modelId,\n        modelPath,\n        port,\n        mlxConfig,\n        envs,\n        isEmbedding,\n        Number(this.timeout)\n      )\n      return sInfo\n    } catch (error) {\n      logger.error(`Error loading MLX model: ${JSON.stringify(error)}`)\n      throw error\n    }\n  }\n\n  override async unload(modelId: string): Promise<UnloadResult> {\n    const sInfo = await this.findSessionByModel(modelId)\n    if (!sInfo) {\n      throw new Error(`No active MLX session found for model: ${modelId}`)\n    }\n\n    try {\n      const result = await unloadMlxModel(sInfo.pid)\n      if (result.success) {\n        logger.info(`Successfully unloaded MLX model with PID ${sInfo.pid}`)\n      } else {\n        logger.warn(`Failed to unload MLX model: ${result.error}`)\n      }\n      return result\n    } catch (error) {\n      logger.error('Error unloading MLX model:', error)\n      return {\n        success: false,\n        error: `Failed to unload model: ${error}`,\n      }\n    }\n  }","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/extensions/mlx-extension/src/index.ts#L307-L343","documentation":"Thrown by unload() when findSessionByModel(modelId) returns nothing — there is no active MLX session for that id, so there is nothing to stop. The extension does not silently no-op; it errors so callers know the model wasn't loaded. Note findSessionByModel itself throws on plugin errors (a different path).","triggerScenarios":"Calling engine.unload(modelId) when the model was never loaded, was already unloaded, or crashed and its session entry was already purged; calling unload with a modelId that differs in casing/format from the loaded one.","commonSituations":"Cleanup/shutdown code unconditionally unloading all models; a user clicks 'stop' on a model that already crashed and was auto-unloaded; retry logic that re-issues unload after a prior success.","solutions":["Guard unload calls with findSessionByModel (or getLoadedModels) and skip if absent.","Treat 'not loaded' as a no-op success in cleanup paths rather than an error.","Verify the modelId string matches the id used at load() time."],"exampleFix":"// before\nawait engine.unload(modelId)\n\n// after\nconst sInfo = await engine.findSessionByModel(modelId).catch(() => null)\nif (!sInfo) return { success: true } // nothing to unload\nawait engine.unload(modelId)","handlingStrategy":"validation","validationCode":"const sInfo = await engine.findSessionByModel(modelId).catch(() => null)\nif (!sInfo) return { success: true } // not loaded; treat as no-op\nawait engine.unload(modelId)","typeGuard":null,"tryCatchPattern":"try {\n  await engine.unload(modelId)\n} catch (e) {\n  if (/No active MLX session/.test(String(e))) return { success: true }\n  throw e\n}","preventionTips":["Guard all cleanup-path unload calls with a session existence check.","Make 'not loaded' a no-op success in shutdown logic.","Match modelId casing/format to the loaded id."],"tags":["session","unload","validation","mlx","typescript"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}