oraios/serena · error · InvalidTextLocationError

InvalidTextLocationError

Error message

InvalidTextLocationError

What it means

InvalidTextLocationError raised by TextStepper.step_to (src/solidlsp/ls_utils.py:143) when the requested line number cannot be reached by stepping through the text — i.e. the target line exceeds the number of lines in the document.

Source

Thrown at src/solidlsp/ls_utils.py:143

            self.line_start_idx = newline_end_idx
        else:
            self.idx = self._len
            self.col = self._len - self.line_start_idx
            self.is_newline = False
        return True

    def step_to(self, line: int, col: int):
        """
        Steps through the text until the given line and column are reached, or until the end of the text is reached.

        :param line: the 0-based line number to step to
        :param col: the 0-based column number to step to
        """
        while self.line < line:
            if not self.step_line():
                break
        if self.line != line:
            raise InvalidTextLocationError
        self.idx += col
        self.col = col

    def process_all(self):
        """
        Processes all characters in the text, updating the line and column numbers accordingly.
        """
        while self.step_line():
            pass

    def get_last_line(self, with_end: bool) -> str:
        """
        Returns the last line processed, optionally including the newline character(s) at the end
        """
        start_idx = self.prev_line_start_idx
        end_idx = self.prev_line_end_idx if not with_end else self.line_start_idx
        return self._chars[start_idx:end_idx]

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Clamp/validate line and col against the text's actual line count before calling.
  2. Recompute positions from the current file contents instead of stale cached values.
  3. Confirm consistent 0-based line/column conventions.

Example fix

// before
stepper.step_to(500, 0)  # file has only 120 lines
// after
lines = text.splitlines()
if line < len(lines):
    stepper.step_to(line, col)
Defensive patterns

Strategy: validation

Validate before calling

def line_exists(text: str, line: int) -> bool:
    return 0 <= line < len(text.splitlines())

Type guard

def valid_position(text: str, line: int, col: int) -> bool:
    lines = text.splitlines()
    return 0 <= line < len(lines) and 0 <= col <= len(lines[line])

Try / catch

try:
    stepper.step_to(line, col)
except InvalidTextLocationError:
    line = len(text.splitlines()) - 1
    stepper.step_to(line, col)

Prevention

When it happens

Trigger: Calling step_to(line, col) (directly or via delete_symbol) with a line index beyond the end of the text, typically because a stale position was cached before the file was edited/shortened.

Common situations: Positions computed against an older file version then reused after edits; off-by-one or 1-based vs 0-based line confusion; parsing a document that changed on disk.

Related errors


AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29). Data as JSON: /api/errors/31da7663f7910c6e. Report an issue: GitHub.