{"record":{"id":"bf5a485905da377a","repo":"OpenBMB/ChatDev","slug":"start-line-is-beyond-the-end-of-the-file","errorCode":null,"errorMessage":"start_line is beyond the end of the file","messagePattern":"start_line is beyond the end of the file","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"functions/function_calling/file.py","lineNumber":964,"sourceCode":"        \"replacement\": replacement if replacement is not None else \"\",\n    }\n    return [payload]\n\n\ndef _validate_edit_ranges(edits: Sequence[TextEdit]) -> None:\n    previous_range_end = 0\n    for edit in edits:\n        effective_end = max(edit.end_line, edit.start_line - 1)\n        if edit.start_line <= previous_range_end and previous_range_end > 0:\n            raise ValueError(\"edit ranges overlap; merge them before calling apply_text_edits\")\n        previous_range_end = max(previous_range_end, effective_end)\n\n\ndef _apply_edits_in_place(lines: MutableSequence[str], edits: Sequence[TextEdit]) -> None:\n    for edit in reversed(edits):\n        current_line_count = len(lines)\n        if edit.start_line > current_line_count + 1:\n            raise ValueError(\"start_line is beyond the end of the file\")\n        start_idx = min(edit.start_line - 1, current_line_count)\n        if start_idx > current_line_count:\n            raise ValueError(\"start_line is beyond the end of the file\")\n        removal_count = max(edit.end_line - edit.start_line + 1, 0)\n        if removal_count > 0:\n            end_line = min(edit.end_line, len(lines))\n            removal_count = max(end_line - edit.start_line + 1, 0)\n        end_idx = start_idx + removal_count\n        lines[start_idx:end_idx] = edit.replacement_lines\n\n\ndef _resolve_newline_choice(preference: str, detected: str) -> str:\n    normalized = (preference or \"\").lower()\n    if normalized == \"lf\":\n        return \"\\n\"\n    if normalized == \"crlf\":\n        return \"\\r\\n\"\n    if normalized == \"cr\":","sourceCodeStart":946,"sourceCodeEnd":982,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/functions/function_calling/file.py#L946-L982","documentation":"When applying edits bottom-up, _apply_edits_in_place rejects any edit whose start_line exceeds the current line count + 1. Appending at end-of-file (start_line == count+1) is allowed, but beyond that the edit would leave a gap of nonexistent lines, so it fails. Typically caused by stale line numbers after the file shrank or was edited by another step.","triggerScenarios":"start_line=100 on a 20-line file; using line numbers from a newer/older version of the file than the one on disk; multiple sequential apply calls where earlier edits changed line counts and later edits weren't recomputed.","commonSituations":"TOCTOU between reading the file and applying edits; concurrent modifications by formatters/linters/other agents; line numbers computed against a buffer with unsaved extra content.","solutions":["Re-read the file and recompute line numbers immediately before applying edits","Verify start_line <= current_line_count + 1 (and prefer exact line targeting) before the call","Apply edits in a single batch from one consistent file snapshot instead of several rounds"],"exampleFix":"# before\napply_text_edits(path=\"a.py\", edits=[{\"start_line\": 100, \"replacement\": \"x\"}])  # file has 20 lines\n# after\ncontent = read_file(\"a.py\")\nn = len(content.splitlines())\napply_text_edits(path=\"a.py\", edits=[{\"start_line\": min(100, n + 1), \"replacement\": \"x\"}])","handlingStrategy":"validation","validationCode":"n_lines = len(Path(ws, path).read_text().splitlines())\nfor e in edits:\n    e[\"start_line\"] = min(e[\"start_line\"], n_lines + 1)\napply_text_edits(path=path, edits=edits)","typeGuard":"def within_file(edits, n_lines) -> bool:\n    return all(e[\"start_line\"] <= n_lines + 1 for e in edits)","tryCatchPattern":"try:\n    apply_text_edits(path=path, edits=edits)\nexcept ValueError as e:\n    if \"beyond the end of the file\" in str(e):\n        raise RuntimeError(f\"stale line numbers for {path}; re-read and retry\") from e\n    raise","preventionTips":["Read the file and derive line numbers in the same tick as the edit","Avoid concurrent writes (formatters, other agents) between read and apply","Batch edits instead of multiple sequential applications"],"tags":["validation","text-edit","out-of-range"],"backgroundTag":"line-number-out-of-range","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}