{"record":{"id":"739f5f0253ce6eb3","repo":"janhq/jan","slug":"model-modelid-does-not-exist-739f5f","errorCode":null,"errorMessage":"Model ${modelId} does not exist","messagePattern":"Model (.+?) does not exist","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"extensions/mlx-extension/src/index.ts","lineNumber":512,"sourceCode":"            throw new Error(error.message)\n          }\n        }\n      }\n    } finally {\n      reader.releaseLock()\n    }\n  }\n\n  override async delete(modelId: string): Promise<void> {\n    const modelDir = await joinPath([\n      await this.getProviderPath(),\n      'models',\n      modelId,\n    ])\n\n    const modelConfigPath = await joinPath([modelDir, 'model.yml'])\n    if (!(await fs.existsSync(modelConfigPath))) {\n      throw new Error(`Model ${modelId} does not exist`)\n    }\n\n    const modelConfig = await invoke<ModelConfig>('read_yaml', {\n      path: modelConfigPath,\n    })\n\n    // Check if model_path is a relative path within mlx folder\n    if (!isAbsoluteModelPath(modelConfig.model_path)) {\n      // Model file is at {janDataFolder}/{model_path}\n      // Delete the parent folder containing the actual model file\n      const janDataFolderPath = await getJanDataFolderPath()\n      const modelPath = await joinPath([\n        janDataFolderPath,\n        modelConfig.model_path,\n      ])\n      const parentDir = modelPath.substring(0, modelPath.lastIndexOf('/'))\n      // Only delete if it's different from modelDir (i.e., not the same folder)\n      if (parentDir !== modelDir) {","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/extensions/mlx-extension/src/index.ts#L494-L530","documentation":"Thrown by delete() when the target folder's model.yml is absent. delete() resolves provider/models/<modelId>/model.yml and refuses to proceed if it does not exist, because without the config it cannot know the model_path to clean up weights. This guards against deleting arbitrary/empty folders.","triggerScenarios":"Calling delete() on a modelId that was never imported, was already deleted, or whose model.yml was removed manually while weights remain; a modelId with wrong casing/separators that doesn't resolve to the real folder.","commonSituations":"UI delete action fired twice (second finds it gone); partial delete earlier removed model.yml but not the folder; user manually cleaned model.yml; stale model list shows an id whose folder is gone.","solutions":["Refresh the model list before offering delete so it reflects actual disk state.","If weights remain without model.yml, locate the model file under the jan data folder and remove it manually, then clear the list entry.","Guard delete() callers with a list()/exists check and no-op if absent.","Verify modelId casing/format matches the imported id."],"exampleFix":"// before\nawait engine.delete(modelId)\n\n// after\nconst cfg = await joinPath([await engine.getProviderPath(), 'models', modelId, 'model.yml'])\nif (!(await fs.existsSync(cfg))) {\n  logger.warn(`Model ${modelId} already gone; nothing to delete`)\n  return\n}\nawait engine.delete(modelId)","handlingStrategy":"validation","validationCode":"async function modelInstalled(providerPath: string, modelId: string): Promise<boolean> {\n  const p = await joinPath([providerPath, 'models', modelId, 'model.yml'])\n  return fs.existsSync(p)\n}\n\nif (!(await modelInstalled(await engine.getProviderPath(), modelId))) {\n  logger.warn(`Model ${modelId} not present; skipping delete`)\n  return\n}","typeGuard":null,"tryCatchPattern":"try {\n  await engine.delete(modelId)\n} catch (e) {\n  if (/does not exist/.test(String(e))) return // already gone\n  throw e\n}","preventionTips":["Refresh engine.list() before offering delete.","Make delete idempotent in UI (no-op if already gone).","Clear stale list entries when a folder is removed out-of-band."],"tags":["filesystem","model-config","delete","validation","mlx","typescript"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}