{"record":{"id":"98bb1631390f68b5","repo":"FoundationAgents/MetaGPT","slug":"invalid-end-line-number-end-line-numbers-must","errorCode":null,"errorMessage":"Invalid end line number: {end}. Line numbers must be between 1 and {len(lines)} (inclusive).","messagePattern":"Invalid end line number: (.+?)\\. Line numbers must be between 1 and (.+?) \\(inclusive\\)\\.","errorType":"exception","errorClass":"LineNumberError","httpStatus":null,"severity":"error","filePath":"metagpt/tools/libs/editor.py","lineNumber":465,"sourceCode":"            end: int: The end line number for editing.\n            content: str: The content to replace the lines with.\n\n        Returns:\n            content: str: The new content of the file.\n            n_added_lines: int: The number of lines added to the file.\n        \"\"\"\n        # Handle cases where start or end are None\n        if start is None:\n            start = 1  # Default to the beginning\n        if end is None:\n            end = len(lines)  # Default to the end\n        # Check arguments\n        if not (1 <= start <= len(lines)):\n            raise LineNumberError(\n                f\"Invalid start line number: {start}. Line numbers must be between 1 and {len(lines)} (inclusive).\"\n            )\n        if not (1 <= end <= len(lines)):\n            raise LineNumberError(\n                f\"Invalid end line number: {end}. Line numbers must be between 1 and {len(lines)} (inclusive).\"\n            )\n        if start > end:\n            raise LineNumberError(f\"Invalid line range: {start}-{end}. Start must be less than or equal to end.\")\n\n        # Split content into lines and ensure it ends with a newline\n        if not content.endswith(\"\\n\"):\n            content += \"\\n\"\n        content_lines = content.splitlines(True)\n\n        # Calculate the number of lines to be added\n        n_added_lines = len(content_lines)\n\n        # Remove the specified range of lines and insert the new content\n        new_lines = lines[: start - 1] + content_lines + lines[end:]\n\n        # Handle the case where the original lines are empty\n        if len(lines) == 0:","sourceCodeStart":447,"sourceCodeEnd":483,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/tools/libs/editor.py#L447-L483","documentation":"Raised by Editor._edit_impl when the resolved end line is outside 1..len(lines). end defaults to len(lines) when None, so the error implies an explicit bad value: 0, negative, or an end line past the last line of the file. Note len(lines) for a file with trailing newline still equals the visible line count, so end = total_lines is legal but end = total_lines + 1 is not.","triggerScenarios":"editor.edit(path, start=1, end=total+1) to 'include everything' (classic off-by-one); end=0; end derived from a diff hunk header of a newer file version.","commonSituations":"Off-by-one when replacing through the last line; stale end offsets after the file shrank; agents computing end as start + added_lines and overshooting.","solutions":["Clamp end to len(lines): end = min(end, total_lines)","Omit end (pass None) to edit through the end of file","Recount lines right before the edit rather than reusing cached totals"],"exampleFix":"// before\neditor.edit(path, start=1, end=total_lines + 1, content='...')  # ValueError\n\n// after\neditor.edit(path, start=1, end=None, content='...')  # end defaults to len(lines)","handlingStrategy":"validation","validationCode":"n = len(editor.current_file.read_text().splitlines())\nend = n if end is None else min(end, n)\nstart = 1 if start is None else max(1, start)\neditor.edit(path, start=start, end=end, content=content)","typeGuard":"def valid_end(end: int, n: int) -> bool:\n    return 1 <= end <= n","tryCatchPattern":"try:\n    editor.edit(path, start=s, end=e, content=c)\nexcept LineNumberError:\n    n = len(Path(path).read_text().splitlines())\n    editor.edit(path, start=min(s, n), end=min(e, n), content=c)","preventionTips":["Pass end=None to edit through EOF instead of computing it yourself","Beware total_lines+1 when trying to include the last line","Recount lines after any edit that changes file length"],"tags":["editor","line-numbers","off-by-one","metagpt"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}