FoundationAgents/MetaGPT · error · LineNumberError

Invalid line range: {start}-{end}. Start must be less than o

Error message

Invalid line range: {start}-{end}. Start must be less than or equal to end.

What it means

Raised by Editor._edit_impl after both bounds checks pass but start > end, i.e. an inverted line range. The edit splice lines[:start-1] + content + lines[end:] only makes sense for an ordered range, so an inverted range is rejected as a caller bug rather than normalized.

Source

Thrown at metagpt/tools/libs/editor.py:469

            content: str: The new content of the file.
            n_added_lines: int: The number of lines added to the file.
        """
        # Handle cases where start or end are None
        if start is None:
            start = 1  # Default to the beginning
        if end is None:
            end = len(lines)  # Default to the end
        # Check arguments
        if not (1 <= start <= len(lines)):
            raise LineNumberError(
                f"Invalid start line number: {start}. Line numbers must be between 1 and {len(lines)} (inclusive)."
            )
        if not (1 <= end <= len(lines)):
            raise LineNumberError(
                f"Invalid end line number: {end}. Line numbers must be between 1 and {len(lines)} (inclusive)."
            )
        if start > end:
            raise LineNumberError(f"Invalid line range: {start}-{end}. Start must be less than or equal to end.")

        # Split content into lines and ensure it ends with a newline
        if not content.endswith("\n"):
            content += "\n"
        content_lines = content.splitlines(True)

        # Calculate the number of lines to be added
        n_added_lines = len(content_lines)

        # Remove the specified range of lines and insert the new content
        new_lines = lines[: start - 1] + content_lines + lines[end:]

        # Handle the case where the original lines are empty
        if len(lines) == 0:
            new_lines = content_lines

        # Join the lines to create the new content
        content = "".join(new_lines)

View on GitHub (pinned to 11cdf466d0)

Solutions

  1. Swap start and end when you detect start > end before calling
  2. Derive end from start plus the hunk length, never the reverse
  3. Add an assertion in your wrapper: assert 1 <= start <= end <= total_lines

Example fix

// before
editor.edit(path, start=20, end=10, content='...')  # ValueError

// after
if start > end:
    start, end = end, start
editor.edit(path, start=start, end=end, content='...')
Defensive patterns

Strategy: validation

Validate before calling

if start > end:
    start, end = end, start
editor.edit(path, start=start, end=end, content=content)

Type guard

def ordered_range(start: int, end: int) -> bool:
    return start <= end

Try / catch

try:
    editor.edit(path, start=s, end=e, content=c)
except LineNumberError as err:
    if 'Start must be less than or equal to end' in str(err):
        editor.edit(path, start=e, end=s, content=c)
    else:
        raise

Prevention

When it happens

Trigger: editor.edit(path, start=10, end=5, ...); start/end swapped by mistake; a diff parser emitting deletion ranges in reverse after a bad merge.

Common situations: Swapping positional arguments; computing end as start - len(...) and going negative-relative; hand-written range arithmetic in refactoring agents.

Related errors


AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14). Data as JSON: /api/errors/f6a9aef192fef761. Report an issue: GitHub.