can1357/oh-my-pi · error · ToolError
Invalid conflict URI '${raw}': wildcard 'conflict://*' does
Error message
Invalid conflict URI '${raw}': wildcard 'conflict://*' does not accept a scope segment. Drop '/${scopePart}' or use a numeric id. What it means
parseConflictUri rejects a wildcard conflict URI that carries a scope segment. The wildcard conflict://* means 'apply to every currently-registered conflict' and is only valid bare; attaching /scope (e.g. conflict://*/ours) is meaningless because scopes are per-conflict, so the parser throws a ToolError with instructions to either drop the scope or use a specific numeric conflict id.
Source
Thrown at packages/coding-agent/src/tools/conflict-detect.ts:292
* clear actionable message rather than a confusing "not found" later.
*
* `*` is the bulk-write wildcard — only valid as `conflict://*` (no
* scope segment). Use it with `write({ path: "conflict://*", content })`
* to apply `content` (with optional `@ours` / `@theirs` / `@base` /
* `@both` shorthand) to every currently-registered conflict in one shot.
*/
export function parseConflictUri(raw: string): ParsedConflictUri | null {
const match = raw.match(CONFLICT_URI_RE);
if (!match) return null;
const recoveredPrefix = match[1];
const tail = match[2];
const slashIdx = tail.indexOf("/");
const idPart = slashIdx === -1 ? tail : tail.slice(0, slashIdx);
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) {View on GitHub (pinned to 9690622007)
Solutions
- Drop the scope and use bare 'conflict://*' (contents can still use @ours/@theirs/@base/@both tokens for per-conflict resolution).
- If you need a specific side, resolve a numeric id first (from a prior read that registered conflicts) and use 'conflict://<N>/<scope>'.
- Fix URI construction so the wildcard never gets a scope segment appended.
Example fix
// before
write({ path: 'conflict://*/theirs', content });
// after
write({ path: 'conflict://*', content }); // @theirs tokens inside content resolve per-conflict Defensive patterns
Strategy: validation
Validate before calling
function isWildcardScoped(uri) {
return /^conflict:\/\/\*\//.test(uri) || /:conflict:\/\/\*\//.test(uri);
}
if (isWildcardScoped(path)) throw new Error('conflict://* takes no scope'); Try / catch
try {
parseConflictUri(raw);
} catch (err) {
if (String(err?.message).includes("does not accept a scope segment")) {
raw = raw.replace(/\/[^/]+$/, ''); // strip scope from wildcard
} else throw err;
} Prevention
- Never append a scope to conflict://* — put @ours/@theirs/@base tokens in content instead.
- Build URIs with a helper that special-cases the wildcard.
- Resolve specific numeric ids when you need a particular side.
- Validate URIs with a regex before passing them to read/write.
When it happens
Trigger: Passing 'conflict://*/ours', 'conflict://*/theirs', or 'conflict://*/base' as the path argument to a read/write targeting conflicts; an agent templating a scoped URI and substituting * for the id.
Common situations: Agents or scripts that build URIs as `conflict://${id}/${scope}` with id='*' for bulk operations; copy-pasted examples mixing the wildcard bulk-write form with the per-id scope form.
Related errors
- Invalid conflict URI '${raw}': must be 'conflict://<N>', 'co
- Invalid conflict URI '${raw}': scope must be one of 'ours',
- Invalid conflict URI '${raw}': id must be ≥ 1.
- Conflict #${entry.id} has no base section (2-way merge). `@b
- Unsupported language '{value}'. Supported: {}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e1796d2188fddbc5.
Report an issue: GitHub.