can1357/oh-my-pi · error · ToolError
Conflict #${entry.id} has no base section (2-way merge). 'co
Error message
Conflict #${entry.id} has no base section (2-way merge). 'conflict://${entry.id}/base' is only valid for diff3 conflicts. What it means
The scope reader throws when reading conflict://<id>/base for a conflict that has no base section. baseLines/baseLine are only populated for diff3-style conflicts (which record the common ancestor between the ======= and >>>>>>> markers); for plain 2-way conflicts that section doesn't exist, so requesting it throws instead of returning empty content.
Source
Thrown at packages/coding-agent/src/tools/conflict-detect.ts:616
* original file positions.
*
* Bare (no scope) returns the full block including marker lines. A
* scoped view returns only that side's body — `base` throws when the
* recorded conflict is a 2-way merge with no base section.
*/
export function renderConflictRegion(
entry: ConflictEntry,
scope: ConflictScope | undefined,
): { lines: string[]; startLine: number } {
if (scope === "ours") {
return { lines: [...entry.oursLines], startLine: entry.startLine + 1 };
}
if (scope === "theirs") {
return { lines: [...entry.theirsLines], startLine: entry.separatorLine + 1 };
}
if (scope === "base") {
if (entry.baseLines === undefined || entry.baseLine === undefined) {
throw new ToolError(
`Conflict #${entry.id} has no base section (2-way merge). 'conflict://${entry.id}/base' is only valid for diff3 conflicts.`,
);
}
return { lines: [...entry.baseLines], startLine: entry.baseLine + 1 };
}
const out: string[] = [];
out.push(markerLine("<<<<<<<", entry.oursLabel));
out.push(...entry.oursLines);
if (entry.baseLines !== undefined) {
out.push(markerLine("|||||||", entry.baseLabel));
out.push(...entry.baseLines);
}
out.push("=======");
out.push(...entry.theirsLines);
out.push(markerLine(">>>>>>>", entry.theirsLabel));
return { lines: out, startLine: entry.startLine };
}
View on GitHub (pinned to 9690622007)
Solutions
- Read the conflict without a scope (conflict://5) or use /ours and /theirs, which exist for both styles.
- Enable diff3 style (git config merge.conflictStyle diff3) and re-trigger the merge to get a base section, then re-read.
- Check the conflict entry's baseLines (or conflict style) before requesting the base scope in scripts.
Example fix
// before
const base = await read({ path: 'conflict://5/base' }); // 2-way conflict
// after
const whole = await read({ path: 'conflict://5' }); // ours+theirs, safe for both styles Defensive patterns
Strategy: type-guard
Validate before calling
if (entry.baseLines !== undefined) {
const base = await read({ path: `conflict://${entry.id}/base` });
} else {
const whole = await read({ path: `conflict://${entry.id}` });
} Type guard
function supportsBaseScope(entry) {
return entry.baseLines !== undefined && entry.baseLine !== undefined;
} Try / catch
try {
const base = await read({ path: `conflict://${id}/base` });
} catch (err) {
if (String(err?.message).includes('has no base section')) {
const whole = await read({ path: `conflict://${id}` }); // 2-way fallback
} else throw err;
} Prevention
- Check baseLines/baseLine on the conflict entry before requesting /base.
- Enable git config merge.conflictStyle=diff3 if base sections are needed.
- Write scope-iterating code that skips base for 2-way conflicts.
- Prefer reading the whole conflict (no scope) when style is unknown.
When it happens
Trigger: Reading 'conflict://5/base' where conflict 5 came from a 2-way merge; iterating all scopes (ours/theirs/base) for every registered conflict without checking which style produced them; an agent assuming diff3 output on a repo configured with merge.conflictStyle=diff.
Common situations: Repos without git config merge.conflictStyle=diff3/zdiff3; conflicts imported from tools (rebase, cherry-pick) that emit 2-way markers; generic tooling that blindly requests every scope.
Related errors
- Conflict #${entry.id} has no base section (2-way merge). `@b
- Conflict #${entry.id} no longer present in '${entry.displayP
- merge conflict in {} file(s)
- Plugin "${pluginId}" is installed in both user and project s
- Plugin "${pluginId}" is installed in both user and project s
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/3b11659d711fa55c.
Report an issue: GitHub.