janhq/jan · error · Error

Model ${modelId} already exists

Error message

Model ${modelId} already exists

What it means

Thrown by runImport() when configPath (<provider>/models/<modelId>/model.yml) already exists. This is the duplicate-import guard: a model with that exact id was already imported (the yml is the canonical 'this model is installed' marker). It fires after the id-validity check but before any download, so no network work is wasted on a duplicate.

Source

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

      // check for empty parts or path traversal
      const parts = id.split('/')
      return parts.every((s) => s !== '' && s !== '.' && s !== '..')
    }

    if (!isValidModelId(modelId))
      throw new Error(
        `Invalid modelId: ${modelId}. Only alphanumeric and / _ - . characters are allowed.`
      )

    const configPath = await joinPath([
      await this.getProviderPath(),
      'models',
      modelId,
      'model.yml',
    ])
    if (await fs.existsSync(configPath))
      throw new Error(`Model ${modelId} already exists`)

    // this is relative to Jan's data folder
    const modelDir = `${this.providerId}/models/${modelId}`

    // we only use these from opts
    // opts.modelPath: URL to the model file
    // opts.mmprojPath: URL to the mmproj file

    let downloadItems: DownloadItem[] = []

    const maybeDownload = async (path: string, saveName: string) => {
      // if URL, add to downloadItems, and return local path
      if (path.startsWith('https://')) {
        const localPath = `${modelDir}/${saveName}`
        downloadItems.push({
          url: path,
          save_path: localPath,
          proxy: await getProxyConfig(),

View on GitHub (pinned to fad3f12a14)

Solutions

  1. If you intend to re-import, delete the existing model first: await provider.delete(modelId).
  2. Check for the model before importing via the model list / fs.existsSync(configPath) and skip or prompt.
  3. Use a different modelId for the new import if both copies should coexist.
  4. If model.yml is a stale leftover from a failed import, remove the model folder manually then retry.

Example fix

// before
await provider.import('qwen7b', opts) // throws - already exists
// after - re-import path
try {
  await provider.import('qwen7b', opts)
} catch (e) {
  if (/already exists/.test(String(e))) { await provider.delete('qwen7b'); await provider.import('qwen7b', opts) }
  else throw e
}
Defensive patterns

Strategy: validation

Validate before calling

// Check for an existing model.yml before importing
const cfg = await joinPath([await provider.getProviderPath(), 'models', modelId, 'model.yml'])
if (await fs.existsSync(cfg)) {
  // either skip, prompt to overwrite, or delete first
  throw new Error(`'${modelId}' is already imported`)
}

Type guard

async function isModelImported(provider: { getProviderPath(): Promise<string> }, id: string): Promise<boolean> {
  const cfg = await joinPath([await provider.getProviderPath(), 'models', id, 'model.yml'])
  return fs.existsSync(cfg)
}

Try / catch

try { await provider.import(modelId, opts) }
catch (e) {
  if (/already exists/.test(String(e))) { await provider.delete(modelId); await provider.import(modelId, opts) }
  else throw e
}

Prevention

When it happens

Trigger: Calling import('qwen7b', opts) when qwen7b is already in the models list. A prior import completed successfully and the user clicks import again. The model folder exists from a partial/cancelled prior import that still wrote model.yml. Two UI entries race but the in-flight dedupe (pendingImports) didn't catch them because they used different modelId strings that resolve to the same folder.

Common situations: Re-importing after a download error that was actually a validation failure but model.yml had already been written. User cleared the UI list but not the on-disk folder. Migration restored the models folder from backup so ids already exist.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/babaa9ca2d7c8bb2. Report an issue: GitHub.