can1357/oh-my-pi · error · ToolError
Invalid conflict URI '${raw}': id must be ≥ 1.
Error message
Invalid conflict URI '${raw}': id must be ≥ 1. What it means
parseConflictUri throws this when the numeric id parses but is less than 1 (e.g. 'conflict://0'). Conflict ids are 1-based, assigned when a read registers conflicts, so 0 (or a parsed value that isn't finite) can never refer to a real conflict.
Source
Thrown at packages/coding-agent/src/tools/conflict-detect.ts:306
const scopePart = slashIdx === -1 ? undefined : tail.slice(slashIdx + 1);
if (idPart === "*") {
if (scopePart !== undefined) {
throw new ToolError(
`Invalid conflict URI '${raw}': wildcard 'conflict://*' does not accept a scope segment. Drop '/${scopePart}' or use a numeric id.`,
);
}
return recoveredPrefix !== undefined ? { id: "*", recoveredPrefix } : { id: "*" };
}
if (!/^\d+$/.test(idPart)) {
throw new ToolError(
`Invalid conflict URI '${raw}': must be 'conflict://<N>', 'conflict://<N>/<scope>', or 'conflict://*' where N is a positive integer surfaced by a prior \`read\`.`,
);
}
const id = Number.parseInt(idPart, 10);
if (!Number.isFinite(id) || id < 1) {
throw new ToolError(`Invalid conflict URI '${raw}': id must be ≥ 1.`);
}
let scope: ConflictScope | undefined;
if (scopePart !== undefined) {
if (!CONFLICT_SCOPES.has(scopePart as ConflictScope)) {
throw new ToolError(
`Invalid conflict URI '${raw}': scope must be one of 'ours', 'theirs', 'base', or omitted (e.g. 'conflict://${id}/theirs').`,
);
}
scope = scopePart as ConflictScope;
}
return recoveredPrefix !== undefined ? { id, scope, recoveredPrefix } : { id, scope };
}
/** Result of {@link spliceConflict}: the new file text plus any boundary-echo repair applied. */
export interface ConflictSplice {
text: string;View on GitHub (pinned to 9690622007)
Solutions
- Use the actual 1-based id from the conflict entry (entry.id from the read result), not an array index.
- Add 1 if you are mapping a zero-based list index to conflict ids — or better, read entry.id directly.
- Guard your code: if no conflict was registered, don't construct a conflict:// URI at all.
Example fix
// before
const uri = `conflict://${index}`; // index is 0-based
// after
const uri = `conflict://${entry.id}`; // entry.id is 1-based Defensive patterns
Strategy: validation
Validate before calling
if (typeof id === 'number' && (!Number.isFinite(id) || id < 1)) {
throw new Error('conflict ids are 1-based; got ' + id);
}
const uri = `conflict://${id}`; Type guard
function isValidConflictId(id) {
return Number.isInteger(id) && id >= 1;
} Try / catch
try {
parseConflictUri(raw);
} catch (err) {
if (String(err?.message).includes('id must be ≥ 1')) {
// id was 0 or invalid — re-derive from conflict entries
} else throw err;
} Prevention
- Use entry.id (1-based), never zero-based array indices.
- Check that a conflict actually exists before building its URI.
- Default to 'no conflict' handling instead of id 0 when the list is empty.
When it happens
Trigger: Passing 'conflict://0' or a computed id that evaluated to 0; off-by-one logic treating conflict ids as zero-indexed; a variable defaulting to 0 when no conflict was found.
Common situations: Scripts using zero-based array indices directly as conflict ids; agents guessing id 0 for 'the first conflict' when the first id is 1.
Related errors
- Invalid conflict URI '${raw}': wildcard 'conflict://*' does
- Invalid conflict URI '${raw}': must be 'conflict://<N>', 'co
- Invalid conflict URI '${raw}': scope must be one of 'ours',
- Conflict #${entry.id} no longer present in '${entry.displayP
- Conflict #${entry.id} has no base section (2-way merge). `@b
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c9242a6af221bf18.
Report an issue: GitHub.