janhq/jan · error · Error
Model with ID ${model.id} already exists
Error message
Model with ID ${model.id} already exists What it means
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.
Source
Thrown at extensions/llamacpp-extension/src/index.ts:3023
* @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 fad3f12a14)
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/.
Example fix
// before
await provider.update('my-model', { id: 'qwen' }) // qwen already exists
// after
const dest = await joinPath([await provider.getProviderPath(), 'models', 'qwen'])
if (await fs.existsSync(dest)) await provider.delete('qwen')
await provider.update('my-model', { id: 'qwen' }) Defensive patterns
Strategy: validation
Validate before calling
// Ensure destination is free before renaming
const dest = await joinPath([await provider.getProviderPath(), 'models', model.id])
if (await fs.existsSync(dest)) {
throw new Error(`Refusing rename: destination '${model.id}' already exists`)
} Type guard
async function isModelIdFree(provider: { getProviderPath(): Promise<string> }, id: string): Promise<boolean> {
const dir = await joinPath([await provider.getProviderPath(), 'models', id])
return !(await fs.existsSync(dir))
} Try / catch
try { await provider.update(oldId, { id: newId }) }
catch (e) {
if (/already exists/.test(String(e))) { await provider.delete(newId); await provider.update(oldId, { id: newId }) }
else throw e
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Model ${modelId} already exists
- File not found: ${path}
- Model ${modelId} does not exist
- model.yml not found for ${modelId}
- Model with ID ${model.id} already exists
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/4544e955891a2e3e.
Report an issue: GitHub.