can1357/oh-my-pi · error · ApplyPatchError

Line hint ${lineHintForInsertion} is out of range for insert

Error message

Line hint ${lineHintForInsertion} is out of range for insertion in ${path} (file has ${originalLines.length} lines)

What it means

Companion to error 1186: for a pure-insertion hunk with a line hint, the hint may point at most one past the end of the file (file length + 1, i.e. append). If lineHintForInsertion exceeds originalLines.length + 1, there is no such insertion point and the patcher throws, reporting the actual file length.

Source

Thrown at packages/coding-agent/src/edit/modes/patch.ts:1187

		if (hunk.oldLines.length === 0) {
			// Pure addition - prefer changeContext position, then line hint, then end of file
			let insertionIdx: number;
			if (hunk.changeContext !== undefined) {
				// changeContext was processed above; lineIndex is set to the context line or after it
				insertionIdx = lineIndex;
			} else {
				const lineHintForInsertion = hunk.oldStartLine ?? hunk.newStartLine;
				if (lineHintForInsertion !== undefined) {
					// Reject if line hint is out of range for insertion
					// Valid insertion points are 1 to (file length + 1) for 1-indexed hints
					if (lineHintForInsertion < 1) {
						throw new ApplyPatchError(
							`Line hint ${lineHintForInsertion} is out of range for insertion in ${path} ` +
								`(line numbers start at 1)`,
						);
					}
					if (lineHintForInsertion > originalLines.length + 1) {
						throw new ApplyPatchError(
							`Line hint ${lineHintForInsertion} is out of range for insertion in ${path} ` +
								`(file has ${originalLines.length} lines)`,
						);
					}
					insertionIdx = Math.max(0, lineHintForInsertion - 1);
				} else {
					insertionIdx =
						originalLines.length > 0 && originalLines[originalLines.length - 1] === ""
							? originalLines.length - 1
							: originalLines.length;
				}
			}

			replacements.push({ startIndex: insertionIdx, oldLen: 0, newLines: [...hunk.newLines] });
			continue;
		}

		// Try to find the old lines in the file

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-read the file, count its lines, and set the hint to a value <= file length + 1 (length + 1 appends).
  2. Drop the line hint to append at end of file.
  3. Anchor the insertion with a @@ changeContext instead of a raw line number.
  4. Regenerate the patch from the file's current content.

Example fix

// before (file has 42 lines)
@@ -99,0 +99,3 @@
+appended lines

// after
@@ -43,0 +43,3 @@
+appended lines
Defensive patterns

Strategy: validation

Validate before calling

const lineCount = (await Bun.file(path).text()).split('\n').length;
if (lineHint !== undefined && lineHint > lineCount + 1) {
  throw new Error(`Insertion hint ${lineHint} exceeds ${path} (${lineCount} lines); max is ${lineCount + 1}.`);
}

Type guard

function isValidInsertionHint(hint: number, fileLineCount: number): boolean {
  return hint >= 1 && hint <= fileLineCount + 1;
}

Try / catch

try {
  applyPatch(patch);
} catch (err) {
  if (err instanceof ApplyPatchError && err.message.includes('file has')) {
    // re-read file, clamp hint to lineCount + 1 (append), retry
  } else throw err;
}

Prevention

When it happens

Trigger: An addition-only hunk whose oldStartLine/newStartLine hint is greater than the target file's line count + 1, with no @@ anchor to position it.

Common situations: Patch written against an older, longer revision of the file that has since been truncated or rewritten; hallucinated line numbers from an LLM; patch reused across similar files of different lengths.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/5d9c464436e931c6. Report an issue: GitHub.