coleam00/Archon · error
node artifact id collision: distinct producers both map to f
Error message
node artifact id collision: distinct producers both map to filename segment '${stem}' What it means
writeNodeArtifact persists each workflow node's output as a markdown file whose filename comes from safeSegment(nodeId) (plus a loop digest for loop iterations). safeSegment can collapse distinct node ids onto the same filename segment (e.g. `a.b` and `a_b`), so before writing, the function reads the artifact owner recorded in the sidecar meta file; if a different producer already owns that path it throws instead of overwriting the other node's artifact.
Source
Thrown at packages/workflows/src/artifacts-index.ts:129
const parsedParams = nodeArtifactWriteParamsSchema.parse(params);
const nodesDir = join(artifactsDir, NODES_SUBDIR);
await mkdir(nodesDir, { recursive: true });
const owner: ArtifactOwner = {
nodeId: parsedParams.nodeId,
...(parsedParams.loopGroupPath !== undefined
? { loopGroupPath: parsedParams.loopGroupPath }
: {}),
};
const stem = artifactStem(owner);
const metaPath = join(nodesDir, `${stem}.meta.json`);
// Collision guard: top-level safeSegment() can collapse distinct node ids (for
// example `a.b` and `a_b`), and loop digests retain an ownership check rather
// than assuming their hash alone is authoritative. Compare the complete
// producer identity and fail loudly instead of overwriting another artifact.
const priorOwner = await readArtifactOwner(metaPath);
if (priorOwner !== undefined && !sameArtifactOwner(priorOwner, owner)) {
throw new Error(
`node artifact id collision: distinct producers both map to filename segment '${stem}'`
);
}
const relPath = join(NODES_SUBDIR, `${stem}.md`);
await writeFile(join(artifactsDir, relPath), outputText, 'utf8');
const meta: NodeArtifact = {
nodeId: parsedParams.nodeId,
outputType: parsedParams.outputType,
...(parsedParams.loopGroupPath !== undefined
? { loopGroupPath: parsedParams.loopGroupPath }
: {}),
path: relPath,
runId: parsedParams.runId,
producedAt: parsedParams.producedAt,
size: Buffer.byteLength(outputText, 'utf8'),
...(parsedParams.sessionId !== undefined ? { sessionId: parsedParams.sessionId } : {}),
};View on GitHub (pinned to 0773b97458)
Solutions
- Rename one of the colliding nodes in the workflow YAML so their ids sanitize to distinct filename segments (avoid mixing '.' and '_' variants of the same name).
- Delete stale artifacts for the run's output directory if the collision comes from leftovers of a previous, differently-shaped run.
- If it occurs on resume after renaming a node, clear the run's artifacts directory or start a fresh run so owner records reset.
- Reproduce with the workflow's node-id list through safeSegment locally to confirm which pair collapses, then adjust ids accordingly.
Example fix
# before: two nodes in one workflow - id: step.one - id: step_one # after: distinct sanitized segments - id: step-one - id: step-summary
Defensive patterns
Strategy: validation
Validate before calling
const segment = (id: string) => id.toLowerCase().replace(/[^a-z0-9]+/g, '_');
const seen = new Set<string>();
for (const node of workflow.nodes) {
const s = segment(node.id);
if (seen.has(s)) throw new Error(`Node ids ${[...seen].find(x => segment(x) === s)} and ${node.id} collide in artifact filenames`);
seen.add(s);
} Try / catch
try {
await writeNodeArtifact(artifactsDir, owner, stem, outputText);
} catch (e) {
if (/node artifact id collision/i.test(e?.message ?? '')) {
logError(`Artifact filename segment '${stem}' is claimed by two producers; rename a node id.`);
} else throw e;
} Prevention
- Choose node ids that sanitize to unique strings (avoid `a.b` vs `a_b` pairs).
- Lint workflow YAML for post-sanitization id uniqueness before running.
- Clear a run's artifacts directory when resuming after renaming node ids.
- Never hand-edit or delete artifact sidecar owner files in a live run directory.
When it happens
Trigger: Two distinct node ids in the same run normalize to the same filename segment under safeSegment (characters like '.' vs '_' collapsed, or case/whitespace folding), and the second node writes its artifact to the already-claimed metaPath while a different owner is recorded.
Common situations: Workflow authors naming nodes `step.one` and `step_one` (or similar near-identical ids) in one workflow; a loop node whose digest coincides with another node's id segment after sanitization; a renamed node in a resumed run colliding with artifacts written by the old id; hand-edited artifacts leaving a stale owner file.
Related errors
- Error loading workflows: ${err.message} Hint: Check permissi
- Failed to update conversation: ${err.message}
- Cannot resume workflow '${workflowName}': failed to load pri
- Corrupt commands JSON for codebase ${id}: unable to parse st
- Multiple packaged workflows declare the name '${name}'
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/6965fcfd760391c0.
Report an issue: GitHub.