nexu-io/open-design · error
cannot overwrite built-in automation template ${template.id}
Error message
cannot overwrite built-in automation template ${template.id} What it means
Thrown by upsertUserAutomationTemplate when the normalized template id collides with one of the six built-in templates: ingest-source-memory-tree, extract-design-system, crystallize-run-into-skill, connector-digest-design-context, compress-project-context, promote-artifact-style. Built-ins are curated and cannot be overwritten through the user upsert path.
Source
Thrown at apps/daemon/src/automation-templates.ts:328
...BUILT_IN_AUTOMATION_TEMPLATES,
...userTemplates.filter((template) => !builtInIds.has(template.id)),
];
}
export async function getAnyAutomationTemplate(
dataDir: string,
id: string,
): Promise<AutomationTemplate | null> {
return (await listAllAutomationTemplates(dataDir)).find((template) => template.id === id) ?? null;
}
export async function upsertUserAutomationTemplate(
dataDir: string,
input: unknown,
): Promise<AutomationTemplate> {
const template = normalizeAutomationTemplate(input);
if (BUILT_IN_AUTOMATION_TEMPLATES.some((builtIn) => builtIn.id === template.id)) {
throw new Error(`cannot overwrite built-in automation template ${template.id}`);
}
const current = await readUserAutomationTemplates(dataDir);
const next = current.filter((existing) => existing.id !== template.id);
next.push(template);
next.sort((a, b) => a.id.localeCompare(b.id));
await writeUserAutomationTemplates(dataDir, next);
return template;
}
View on GitHub (pinned to 5be4028344)
Solutions
- Rename the id to something unique, e.g. add a suffix ('extract-design-system-v2', 'myteam:compress-context').
- Filter the payload against BUILT_IN_AUTOMATION_TEMPLATES (exported list) before upserting in bulk.
- If you genuinely need to change built-in behavior, that requires a code change to automation-templates.ts, not an upsert.
Example fix
// before
await upsertUserAutomationTemplate(dataDir, {
id: 'extract-design-system', // collides with built-in -> throws
/* ... */
});
// after
await upsertUserAutomationTemplate(dataDir, {
id: 'extract-design-system-custom',
/* ... */
}); Defensive patterns
Strategy: validation
Validate before calling
import { BUILT_IN_AUTOMATION_TEMPLATES } from './automation-templates.js';
const BUILT_IN_IDS = new Set(BUILT_IN_AUTOMATION_TEMPLATES.map(t => t.id));
if (BUILT_IN_IDS.has(payload.id)) {
throw new Error(`Refusing to overwrite built-in template '${payload.id}'. Rename the id.`);
} Type guard
function isUserTemplateId(id: string, builtInIds: Set<string>): boolean {
return !builtInIds.has(id);
} Try / catch
try {
await upsertUserAutomationTemplate(dataDir, payload);
} catch (err) {
if (err instanceof Error && err.message.startsWith('cannot overwrite built-in automation template ')) {
return conflict('Pick a different id; built-in templates cannot be overwritten.');
}
throw err;
} Prevention
- Namespace custom template ids (team prefix, version suffix) so they never collide with built-ins.
- When round-tripping exports, filter out built-in ids before re-importing.
- Changing built-in behavior requires editing automation-templates.ts — never an upsert.
When it happens
Trigger: POSTing a user template whose id exactly matches a built-in; forking a built-in to customize it without renaming; re-importing an export that included built-in templates alongside user ones.
Common situations: An export/import flow that round-trips the full list (built-ins plus user templates) and tries to write the built-ins back; a user copying a built-in as a starting point and forgetting to rename.
Related errors
- automation template ${key} is required
- automation template must be an object
- automation template id must be a safe slug
- automation template requires at least one valid stage
- sourceKind must be one of upload, url, repo, connector, arti
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/90d2772cbad51d75.
Report an issue: GitHub.