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

  1. Reorder so the empty-old_string insertion edit is the first element of edits
  2. Use a real anchor string for subsequent insertions (old_string set to surrounding text)
  3. 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

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


AI-assisted analysis of continuedev/continue@5522c6f44c (2026-08-27). Data as JSON: /api/errors/b8b6ca43d5f6b633. Report an issue: GitHub.