earendil-works/pi · error
Replacement range is outside the base content.
Error message
Replacement range is outside the base content.
What it means
Internal consistency guard in getReplacementLineRange: a matched edit's character range (matchIndex..matchIndex+matchLength) does not fall inside any line span of the base content. This indicates the replacement was matched against different content than the line-indexed base, i.e. an alignment bug or mutated input rather than a user error.
Solutions
- Ensure the same baseContent string is used for matching and line-span computation
- Recompute matches after any normalization instead of reusing stale indices
- Report as an internal bug if it reproduces with a single straightforward edit
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/coding-agent/src/core/tools/edit-diff.ts:97 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of earendil-works/pi@4af9d21d3b (2026-08-24).
Data as JSON: /api/errors/8b1958caefc7da8f.
Report an issue: GitHub.
Appendix: source
Thrown at packages/coding-agent/src/core/tools/edit-diff.ts:97
offset = span.end;
return span;
});
}
function getReplacementLineRange(lines: LineSpan[], replacement: TextReplacement) {
const replacementStart = replacement.matchIndex;
const replacementEnd = replacement.matchIndex + replacement.matchLength;
let startLine = -1;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (replacementStart >= line.start && replacementStart < line.end) {
startLine = i;
break;
}
}
if (startLine === -1) {
throw new Error("Replacement range is outside the base content.");
}
let endLine = startLine;
while (endLine < lines.length && lines[endLine].end < replacementEnd) {
endLine++;
}
if (endLine >= lines.length) {
throw new Error("Replacement range is outside the base content.");
}
return { startLine, endLine: endLine + 1 };
}
function applyReplacements(content: string, replacements: TextReplacement[], offset = 0): string {
let result = content;
for (let i = replacements.length - 1; i >= 0; i--) {
const replacement = replacements[i];
const matchIndex = replacement.matchIndex - offset;View on GitHub (pinned to 4af9d21d3b)