continuedev/continue · error · ContinueError
FindAndReplaceNonFirstEmptyOldString
FindAndReplaceNonFirstEmptyOldString
Error message
Edit at index ${i}: old_string cannot be empty. Only the first edit can have an empty old_string for insertion at the beginning of the file. What it means
Thrown when any edit after the first in a multi-edit batch has an empty old_string. Empty old_string is a special 'insert at beginning of file' form that only makes sense once, at index 0, so subsequent empty-old_string edits are ambiguous and rejected.
Source
Thrown at core/edit/searchAndReplace/multiEditValidation.ts:46
const { edits } = args;
if (edits.length === 0) {
throw new ContinueError(
ContinueErrorReason.MultiEditEditsArrayEmpty,
"edits array must contain at least one edit",
);
}
// Validate each individual edit
for (let i = 0; i < edits.length; i++) {
const edit = edits[i];
// Use existing single edit validation
validateSingleEdit(edit.old_string, edit.new_string, edit.replace_all, i);
// Only the first edit can have empty old_string (for insertion at beginning)
if (i > 0 && edit.old_string === "") {
throw new ContinueError(
ContinueErrorReason.FindAndReplaceNonFirstEmptyOldString,
`Edit at index ${i}: old_string cannot be empty. Only the first edit can have an empty old_string for insertion at the beginning of the file.`,
);
}
}
return { edits };
}
View on GitHub (pinned to 5522c6f44c)
Solutions
- Reorder so the empty-old_string insertion edit is the first element of edits
- Use a real anchor string for subsequent insertions (old_string set to surrounding text)
- Combine multiple top-of-file insertions into a single new_string on the first edit
Example fix
// before
edits: [{ old_string: "", new_string: "// header" }, { old_string: "", new_string: "import x;" }]
// after
edits: [{ old_string: "", new_string: "// header\nimport x;" }] Defensive patterns
Strategy: validation
Validate before calling
edits.forEach((e, i) => { if (i > 0 && e.old_string === '') throw new RangeError('only first edit may be empty'); }); Type guard
const insertionOnlyFirst = (es: Edit[]) => es.every((e, i) => i === 0 || e.old_string !== '');
Prevention
- Sort edits so the insertion is index 0
- Give every other edit a real anchor string
- Merge multiple top insertions into one new_string
When it happens
Trigger: Passing { edits: [{ old_string: "", new_string: "header" }, { old_string: "", new_string: "x" }] } — the second empty edit triggers it.
Common situations: LLMs trying to perform multiple insertions at the top of a file; builders appending 'insert' edits after sorting the array so an insertion is no longer first.
Related errors
- FindAndReplaceIdenticalOldAndNewStrings
- FindAndReplaceInvalidReplaceAll
- MultiEditEditsArrayRequired
- MultiEditEditsArrayEmpty
- FindAndReplaceOldStringNotFound
AI-assisted analysis of continuedev/continue@5522c6f44c (2026-08-27).
Data as JSON: /api/errors/b8b6ca43d5f6b633.
Report an issue: GitHub.