{"record":{"id":"4544e955891a2e3e","repo":"janhq/jan","slug":"model-with-id-model-id-already-exists","errorCode":null,"errorMessage":"Model with ID ${model.id} already exists","messagePattern":"Model with ID (.+?) already exists","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"extensions/llamacpp-extension/src/index.ts","lineNumber":3023,"sourceCode":"   * @param model\n   */\n  async update(modelId: string, model: Partial<modelInfo>): Promise<void> {\n    const modelFolderPath = await joinPath([\n      await this.getProviderPath(),\n      'models',\n      modelId,\n    ])\n    const modelConfig = await invoke<ModelConfig>('read_yaml', {\n      path: await joinPath([modelFolderPath, 'model.yml']),\n    })\n    const newFolderPath = await joinPath([\n      await this.getProviderPath(),\n      'models',\n      model.id,\n    ])\n    // Check if newFolderPath exists\n    if (await fs.existsSync(newFolderPath)) {\n      throw new Error(`Model with ID ${model.id} already exists`)\n    }\n    const newModelConfigPath = await joinPath([newFolderPath, 'model.yml'])\n    await fs.mv(modelFolderPath, newFolderPath).then(() =>\n      // now replace what values have previous model name with format\n      invoke('write_yaml', {\n        data: {\n          ...modelConfig,\n          model_path: modelConfig?.model_path?.replace(\n            `${this.providerId}/models/${modelId}`,\n            `${this.providerId}/models/${model.id}`\n          ),\n          mmproj_path: modelConfig?.mmproj_path?.replace(\n            `${this.providerId}/models/${modelId}`,\n            `${this.providerId}/models/${model.id}`\n          ),\n        },\n        savePath: newModelConfigPath,\n      })","sourceCodeStart":3005,"sourceCodeEnd":3041,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/extensions/llamacpp-extension/src/index.ts#L3005-L3041","documentation":"Thrown by update() (model rename) when the destination folder <provider>/models/<model.id> already exists on disk. The method reads the source model.yml, computes the new folder path from model.id, and refuses to overwrite an existing model directory to prevent a destructive rename collision. fs.mv would otherwise silently swallow the source.","triggerScenarios":"Calling update(oldId, { id: 'newId' }) when a model named 'newId' is already imported. model.id contains trailing whitespace or different casing that resolves to an existing folder on a case-insensitive filesystem. A previous rename partially completed leaving the destination folder behind.","commonSituations":"User tries to rename a model to a name they already used before and deleted incompletely. Import-and-rename workflow where the target id collides with a sibling model. Case-insensitive OS (Windows/macOS) collisions: renaming to a differently-cased id of an existing folder.","solutions":["Choose a new model.id that does not collide - check fs.existsSync of the target folder first.","If the destination is stale, delete that model (delete(model.id)) before renaming.","Sanitize model.id (trim whitespace, normalize case) before calling update to avoid accidental collisions.","If a previous rename crashed mid-way, manually clean up the leftover destination folder under <provider>/models/."],"exampleFix":"// before\nawait provider.update('my-model', { id: 'qwen' }) // qwen already exists\n// after\nconst dest = await joinPath([await provider.getProviderPath(), 'models', 'qwen'])\nif (await fs.existsSync(dest)) await provider.delete('qwen')\nawait provider.update('my-model', { id: 'qwen' })","handlingStrategy":"validation","validationCode":"// Ensure destination is free before renaming\nconst dest = await joinPath([await provider.getProviderPath(), 'models', model.id])\nif (await fs.existsSync(dest)) {\n  throw new Error(`Refusing rename: destination '${model.id}' already exists`)\n}","typeGuard":"async function isModelIdFree(provider: { getProviderPath(): Promise<string> }, id: string): Promise<boolean> {\n  const dir = await joinPath([await provider.getProviderPath(), 'models', id])\n  return !(await fs.existsSync(dir))\n}","tryCatchPattern":"try { await provider.update(oldId, { id: newId }) }\ncatch (e) {\n  if (/already exists/.test(String(e))) { await provider.delete(newId); await provider.update(oldId, { id: newId }) }\n  else throw e\n}","preventionTips":["Trim and slugify model.id before offering the rename.","Check the destination folder before allowing the rename to commit.","On case-insensitive filesystems, warn when the new id differs only by case from an existing one."],"tags":["model","rename","filesystem","collision","validation"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}