{"record":{"id":"50e480ec44ce4e11","repo":"OpenBMB/ChatDev","slug":"end-line-must-be-start-line-1","errorCode":null,"errorMessage":"end_line must be >= start_line - 1","messagePattern":"end_line must be >= start_line - 1","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"functions/function_calling/file.py","lineNumber":920,"sourceCode":"    if not edits:\n        raise ValueError(\"at least one edit instruction is required\")\n    normalized: List[TextEdit] = []\n    for item in edits:\n        if not isinstance(item, Mapping):\n            raise ValueError(\"each edit entry must be a mapping object\")\n        try:\n            start_line = int(item[\"start_line\"])\n        except (KeyError, TypeError, ValueError) as exc:\n            raise ValueError(\"start_line is required for each edit\") from exc\n        end_line_raw = item.get(\"end_line\", start_line)\n        try:\n            end_line = int(end_line_raw)\n        except (TypeError, ValueError) as exc:\n            raise ValueError(\"end_line must be an integer\") from exc\n        if start_line < 1:\n            raise ValueError(\"start_line must be >= 1\")\n        if end_line < start_line - 1:\n            raise ValueError(\"end_line must be >= start_line - 1\")\n        replacement = item.get(\"replacement\", \"\")\n        if not isinstance(replacement, str):\n            raise ValueError(\"replacement must be a string\")\n        normalized.append(\n            TextEdit(\n                start_line=start_line,\n                end_line=end_line,\n                replacement_lines=replacement.splitlines(),\n            )\n        )\n\n    normalized.sort(key=lambda edit: (edit.start_line, edit.end_line))\n    _validate_edit_ranges(normalized)\n    return normalized\n\n\ndef _build_single_edit(\n    start_line: int,","sourceCodeStart":902,"sourceCodeEnd":938,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/functions/function_calling/file.py#L902-L938","documentation":"After coercion, each edit must satisfy end_line >= start_line - 1. The -1 slack permits pure-deletion edits where end_line = start_line - 1 (delete starting at start_line with empty replacement); anything smaller means the range is inverted or nonsensical. This usually indicates swapped start/end or garbled diff math.","triggerScenarios":"Swapping start_line and end_line (start=10, end=2); decrementing end_line below start_line-1 during range arithmetic; expressing a deletion with end_line = start_line - 2.","commonSituations":"Diff parsers that emit ranges in file-order vs hunk-order inconsistently; LLM-generated edits with inverted ranges; code that clamps end_line incorrectly (e.g. min(end, start-2)).","solutions":["Check whether start_line and end_line are swapped and correct them","For deletions, use end_line = start_line - 1 with the appropriate replacement semantics, or better, set end_line to the last line to delete","Validate ordering (end_line >= start_line - 1) per edit before calling"],"exampleFix":"# before\napply_text_edits(path=\"a.py\", edits=[{\"start_line\": 10, \"end_line\": 2, \"replacement\": \"x\"}])\n# after\napply_text_edits(path=\"a.py\", edits=[{\"start_line\": 2, \"end_line\": 10, \"replacement\": \"x\"}])","handlingStrategy":"validation","validationCode":"for e in edits:\n    if e.get(\"end_line\", e[\"start_line\"]) < e[\"start_line\"] - 1:\n        e[\"start_line\"], e[\"end_line\"] = e[\"end_line\"], e[\"start_line\"]  # un-swap\napply_text_edits(path=path, edits=edits)","typeGuard":"def ranges_ordered(edits) -> bool:\n    return all(\n        e.get(\"end_line\", e[\"start_line\"]) >= e[\"start_line\"] - 1 for e in edits\n    )","tryCatchPattern":"try:\n    apply_text_edits(path=path, edits=edits)\nexcept ValueError as e:\n    if \"end_line must be >= start_line - 1\" in str(e):\n        raise ValueError(f\"inverted range in edits: {edits}\") from e\n    raise","preventionTips":["Compute ranges from one consistent diff source","Sanity-check start <= end when building each edit","Avoid hand-arithmetic on line ranges; derive them programmatically"],"tags":["validation","text-edit","range-error"],"backgroundTag":"invalid-argument-range","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}