can1357/oh-my-pi · error · ToolError
Conflict #${id} not found. Conflict ids are registered when
Error message
Conflict #${id} not found. Conflict ids are registered when `read` surfaces a marker block; re-read the file to get a current id. What it means
Conflict ids are registered only when the `read` tool surfaces a conflict marker block, stored in the session's conflict history. Looking up an id that was never registered (or has been cleared) throws this ToolError telling the caller to re-read the file to obtain a current id.
Source
Thrown at packages/coding-agent/src/tools/write.ts:918
return {
content: [{ type: "text", text: resultText }],
details: { resolvedPath: absolutePath },
};
}
/**
* Look up a single conflict entry by id and dispatch to {@link #resolveConflict}.
* Throws a clear `not found` error when the id has been invalidated.
*/
async #resolveSingleConflictById(
id: number,
replacementContent: string,
stripped: boolean,
signal: AbortSignal | undefined,
): Promise<AgentToolResult<WriteToolDetails>> {
const entry = getConflictHistory(this.session).get(id);
if (!entry) {
throw new ToolError(
`Conflict #${id} not found. Conflict ids are registered when \`read\` surfaces a marker block; re-read the file to get a current id.`,
);
}
return this.#resolveConflict(entry, replacementContent, stripped, signal);
}
/**
* Bulk-resolve every registered conflict via `conflict://*`.
*
* Entries are grouped by file and applied bottom-up by recorded start
* line so each splice keeps later anchors valid. `content` tokens are
* expanded *per entry*, so `content: "@ours"` keeps each block's own
* ours side rather than collapsing every conflict to the first
* block's ours.
*
* All-or-nothing semantics within a file: if any splice for a file
* fails (stale anchors, missing base for `@base`, etc.), that file is
* left untouched and the error is surfaced. Files that succeed areView on GitHub (pinned to 9690622007)
Solutions
- Re-read the file containing the conflict markers to get fresh, currently valid ids.
- List currently registered conflicts (the conflict://* flow reports registered ids in related errors).
- Use conflict://* with per-id directives once you know the valid ids.
- Don't persist conflict ids across sessions — they are session-scoped.
Defensive patterns
Strategy: type-guard
Validate before calling
// keep a local set of ids obtained from the most recent conflict-surfacing read
const knownIds = new Set([1, 2, 5]);
if (!knownIds.has(id)) throw new Error(`#${id} is not a registered conflict id`); Type guard
function isRegisteredConflictId(id: number, entries: { id: number }[]): boolean {
return entries.some(e => e.id === id);
} Try / catch
try {
await write(`conflict://${id}`, replacement);
} catch (err) {
if (String(err.message).includes("not found")) {
// re-read the file to refresh conflict ids, then retry
}
throw err;
} Prevention
- Only use ids emitted by the latest read of the conflicted file.
- Never reuse ids across sessions or after other resolutions.
- Re-read before each conflict resolution pass.
When it happens
Trigger: Calling write with conflict://<id> where the id is wrong, was from a previous session, references a conflict that was already resolved and evicted, or the file was never re-read after new conflicts appeared.
Common situations: Agent hallucinating an id, reusing ids after session restart, stale ids cached in agent notes after another resolution pass consumed them, ids referencing files not read with the conflict-surfacing read path.
Related errors
- Conflict #${entry.id} no longer present in '${entry.displayP
- Conflict #${entry.id} target '${entry.displayPath}' no longe
- Bulk directive references unknown conflict id(s) ${unknown.m
- Selected ${sourceName} session is no longer available
- Invalid conflict URI '${raw}': wildcard 'conflict://*' does
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/5d116db3be0c4991.
Report an issue: GitHub.