deepseek-ai/deepseek-harness · error · PresetExistsError
agent-presets: preset "${presetId}" already exists — a copy
Error message
agent-presets: preset "${presetId}" already exists — a copy never overwrites; delete the existing preset first or choose another id What it means
Error "agent-presets: preset "${presetId}" already exists — a copy never overwrites; delete the existing preset first or choose another id" thrown in deepseek-ai/deepseek-harness.
Source
Thrown at packages/preset/agent-presets/src/index.ts:386
* Copy is the only authoring write. Composition text never crosses this
* seam: the source is named by id and its directory is copied as it stands,
* so the copy is exactly as loadable as its source and authoring grants no
* capability the roster did not already carry. The copy is NOT mounted to
* validate — a source that mounts today yields a copy that mounts today.
* @param from - the preset the copy starts from; shipped presets are the
* primary source, so any trust is accepted.
* @param id - the new preset's id, which becomes its directory name.
* @param name - display name for the copy; absent falls back to the id.
* @throws when the source is unknown, the id is unusable or already taken,
* or the deployment configures no writable root.
*/
async copy(from: string, id: string, name?: string): Promise<void> {
const source = await this.resolve(from)
// The roster check refuses ids any root supplies — shipped ones included,
// since a user directory named like a shipped preset is shadowed by it.
// The disk check inside copyComposition only sees the writable root.
if ((await this.list()).some(preset => preset.id === id)) {
throw new PresetExistsError(id)
}
await copyComposition(this.resolvedRoots, source, id, name)
// A settled mount under this id can only be stale (its preset was deleted
// from disk outside `remove`); the new preset must not inherit it. Every
// session already joined keeps the generation it runs on regardless.
this.standing.delete(id)
}
/**
* Delete a locally authored preset.
* @param id - the preset id.
* @throws when the preset is unknown or ships with the deployment.
*/
async remove(id: string): Promise<void> {
await deleteComposition(this.resolvedRoots, await this.resolve(id))
// Sessions on the deleted preset keep their standing mount; only new
// sessions see the roster without it.
this.standing.delete(id)View on GitHub (pinned to b150a551b8)
Solutions
- Delete the existing preset first, or choose another id.
When it happens
Trigger: Thrown at packages/preset/agent-presets/src/index.ts:386 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/2389c4ecd5814ce5.
Report an issue: GitHub.