janhq/jan · error

Model with ID already exists

Error message

Model with ID ${model.id} already exists

What it means

When importing a model, the extension moves the model folder to <providerPath>/models/<model.id>. If a directory with that ID already exists on disk, it throws 'Model with ID ... already exists' to prevent overwriting the existing model's config and weights.

Solutions

  1. Choose a different model.id for the import
  2. Delete the existing model folder under <providerPath>/models/<id> if it is no longer wanted
  3. Use the provider's model listing to confirm the existing model before re-importing
  4. If the existing folder is a stale partial import, remove it and retry

Example fix

// before
await importModel({ ...model, id: 'llama-3-8b' }) // already exists
// after
await importModel({ ...model, id: 'llama-3-8b-imported' })
Defensive patterns

Strategy: validation

Validate before calling

const target = join(providerPath, 'models', model.id)
if (await fs.existsSync(target)) throw new Error('pick another id or delete first')
await importModel(model)

Try / catch

try {
  await importModel(model)
} catch (e) {
  if (/Model with ID .* already exists/.test(e.message)) {
    model.id = `${model.id}-${Date.now()}`; await importModel(model)
  } else throw e
}

Prevention

When it happens

Trigger: Calling the import flow (llamacpp_extension public method that renames/moves a local model folder) with a model.id that matches an existing folder under the provider's models directory.

Common situations: Re-importing the same GGUF twice; importing a model with an ID identical to a previously imported one; leftover folders from a partially deleted model.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17). Data as JSON: /api/errors/4544e955891a2e3e. Report an issue: GitHub.

Appendix: source

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

   * @param model
   */
  async update(modelId: string, model: Partial<modelInfo>): Promise<void> {
    const modelFolderPath = await joinPath([
      await this.getProviderPath(),
      'models',
      modelId,
    ])
    const modelConfig = await invoke<ModelConfig>('read_yaml', {
      path: await joinPath([modelFolderPath, 'model.yml']),
    })
    const newFolderPath = await joinPath([
      await this.getProviderPath(),
      'models',
      model.id,
    ])
    // Check if newFolderPath exists
    if (await fs.existsSync(newFolderPath)) {
      throw new Error(`Model with ID ${model.id} already exists`)
    }
    const newModelConfigPath = await joinPath([newFolderPath, 'model.yml'])
    await fs.mv(modelFolderPath, newFolderPath).then(() =>
      // now replace what values have previous model name with format
      invoke('write_yaml', {
        data: {
          ...modelConfig,
          model_path: modelConfig?.model_path?.replace(
            `${this.providerId}/models/${modelId}`,
            `${this.providerId}/models/${model.id}`
          ),
          mmproj_path: modelConfig?.mmproj_path?.replace(
            `${this.providerId}/models/${modelId}`,
            `${this.providerId}/models/${model.id}`
          ),
        },
        savePath: newModelConfigPath,
      })

View on GitHub (pinned to 7205d770c1)