{"record":{"id":"3b7c96ad5fdf5115","repo":"can1357/oh-my-pi","slug":"bulk-directive-references-unknown-conflict-id-s","errorCode":null,"errorMessage":"Bulk directive references unknown conflict id(s) ${unknown.map(id => `#${id}`).join(\", \")}. Currently registered: ${allEntries.map(e => `#${e.id}`).join(\", \")}.","messagePattern":"Bulk directive references unknown conflict id\\(s\\) (.+?)`\\)\\.join\\(\", \"\\)\\}\\. Currently registered: (.+?)`\\)\\.join\\(\", \"\\)\\}\\.","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/write.ts","lineNumber":965,"sourceCode":"\t\tconst allEntries = history.entries();\n\t\tif (allEntries.length === 0) {\n\t\t\tthrow new ToolError(\n\t\t\t\t\"`conflict://*` has nothing to resolve — no conflicts are currently registered. Re-read the file(s) with conflicts first.\",\n\t\t\t);\n\t\t}\n\n\t\t// Per-id directive mode: content made solely of `<id>: @side` lines\n\t\t// resolves each listed conflict with that side in one call. Ideal for\n\t\t// merge-hell files where dozens of pick-one blocks each need their own\n\t\t// winner — one call instead of one write per conflict. Parsed from the\n\t\t// PRE-strip content: hashline prefix stripping would otherwise eat the\n\t\t// `<id>: ` heads as echoed line numbers.\n\t\tconst directives = resolveBulkDirectives(rawContent, replacementContent);\n\t\tif (directives) {\n\t\t\tconst known = new Set(allEntries.map(entry => entry.id));\n\t\t\tconst unknown = [...directives.keys()].filter(id => !known.has(id));\n\t\t\tif (unknown.length > 0) {\n\t\t\t\tthrow new ToolError(\n\t\t\t\t\t`Bulk directive references unknown conflict id(s) ${unknown.map(id => `#${id}`).join(\", \")}. Currently registered: ${allEntries.map(e => `#${e.id}`).join(\", \")}.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tconst selectedEntries = directives ? allEntries.filter(entry => directives.has(entry.id)) : allEntries;\n\t\tconst contentFor = (entry: ConflictEntry): string =>\n\t\t\tdirectives ? (directives.get(entry.id) as string) : replacementContent;\n\n\t\tconst byFile = new Map<string, ConflictEntry[]>();\n\t\tfor (const entry of selectedEntries) {\n\t\t\tconst bucket = byFile.get(entry.absolutePath) ?? [];\n\t\t\tbucket.push(entry);\n\t\t\tbyFile.set(entry.absolutePath, bucket);\n\t\t}\n\n\t\tconst succeededFiles: { displayPath: string; count: number; header?: string }[] = [];\n\t\tconst failedFiles: { displayPath: string; count: number; error: string }[] = [];\n\t\tlet totalResolvedIds = 0;","sourceCodeStart":947,"sourceCodeEnd":983,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/write.ts#L947-L983","documentation":"In per-id directive mode, content lines of the form `<id>: @side` select specific conflicts to resolve. Each referenced id must exist in the registered conflict history; if any directive references an unknown id, the tool throws this error listing both the unknown ids and all currently registered ids so the caller can correct the request atomically (nothing is applied).","triggerScenarios":"Calling write with conflict://* and directive content like `3: @ours` where id 3 is not registered — due to typo, eviction, stale session state, or hallucinated ids.","commonSituations":"Agent mixing up ids across multiple conflicted files, ids shifting after re-reads, a partial bulk resolution in an earlier call consumed some ids, model guessing ids without re-reading.","solutions":["Use the 'Currently registered' ids listed in the error message to fix the directive ids.","Re-read the affected files if the registered set looks unfamiliar.","Resend the write with only valid `<id>: @side` directives.","Resolve one conflict per call (conflict://<id>) to avoid id mismatch in bulk mode."],"exampleFix":"// before\ncontent: \"7: @ours\\n9: @theirs\" // #9 unknown\n// after (registered: #2, #5)\ncontent: \"2: @ours\\n5: @theirs\"","handlingStrategy":"validation","validationCode":"const registered = new Set(history.entries().map(e => e.id));\nconst used = [...raw.matchAll(/^(\\d+):\\s*@/gm)].map(m => Number(m[1]));\nconst unknown = used.filter(id => !registered.has(id));\nif (unknown.length) throw new Error(`Unknown conflict ids: ${unknown.join(\", \")}`);","typeGuard":null,"tryCatchPattern":"try {\n  await write(\"conflict://*\", directiveContent);\n} catch (err) {\n  const m = String(err.message).match(/Currently registered: (.+)\\./);\n  if (m) {\n    const valid = m[1].match(/#(\\d+)/g);\n    // rebuild directives using only listed ids\n  }\n  throw err;\n}","preventionTips":["Copy directive ids directly from the error's 'Currently registered' list.","Re-read files after any resolution pass — ids can be consumed or shift.","Prefer per-id conflict://<id> writes when unsure of the full id set."],"tags":["conflict-resolution","invalid-id","bulk-resolve"],"backgroundTag":"unknown-resource-id","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}