{"record":{"id":"b8b6ca43d5f6b633","repo":"continuedev/continue","slug":"findandreplacenonfirstemptyoldstring","errorCode":"FindAndReplaceNonFirstEmptyOldString","errorMessage":"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.","messagePattern":"Edit at index (.+?): old_string cannot be empty\\. Only the first edit can have an empty old_string for insertion at the beginning of the file\\.","errorType":"validation","errorClass":"ContinueError","httpStatus":null,"severity":"error","filePath":"core/edit/searchAndReplace/multiEditValidation.ts","lineNumber":46,"sourceCode":"  const { edits } = args;\n\n  if (edits.length === 0) {\n    throw new ContinueError(\n      ContinueErrorReason.MultiEditEditsArrayEmpty,\n      \"edits array must contain at least one edit\",\n    );\n  }\n\n  // Validate each individual edit\n  for (let i = 0; i < edits.length; i++) {\n    const edit = edits[i];\n\n    // Use existing single edit validation\n    validateSingleEdit(edit.old_string, edit.new_string, edit.replace_all, i);\n\n    // Only the first edit can have empty old_string (for insertion at beginning)\n    if (i > 0 && edit.old_string === \"\") {\n      throw new ContinueError(\n        ContinueErrorReason.FindAndReplaceNonFirstEmptyOldString,\n        `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.`,\n      );\n    }\n  }\n\n  return { edits };\n}\n","sourceCodeStart":28,"sourceCodeEnd":55,"githubUrl":"https://github.com/continuedev/continue/blob/5522c6f44ca0ac3528b37244818fbfa39b5af470/core/edit/searchAndReplace/multiEditValidation.ts#L28-L55","documentation":"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.","triggerScenarios":"Passing { edits: [{ old_string: \"\", new_string: \"header\" }, { old_string: \"\", new_string: \"x\" }] } — the second empty edit triggers it.","commonSituations":"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.","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"],"exampleFix":"// before\nedits: [{ old_string: \"\", new_string: \"// header\" }, { old_string: \"\", new_string: \"import x;\" }]\n// after\nedits: [{ old_string: \"\", new_string: \"// header\\nimport x;\" }]","handlingStrategy":"validation","validationCode":"edits.forEach((e, i) => { if (i > 0 && e.old_string === '') throw new RangeError('only first edit may be empty'); });","typeGuard":"const insertionOnlyFirst = (es: Edit[]) => es.every((e, i) => i === 0 || e.old_string !== '');","tryCatchPattern":null,"preventionTips":["Sort edits so the insertion is index 0","Give every other edit a real anchor string","Merge multiple top insertions into one new_string"],"tags":["multi-edit","find-and-replace","insertion","ordering"],"backgroundTag":"edit-ordering-constraint","analyzedSha":"5522c6f44ca0ac3528b37244818fbfa39b5af470","analyzedAt":"2026-08-27T11:28:54.683Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}