langchain-ai/deepagents · error · ValueError
ReadResult window must satisfy 1 <= start_line <= end_line,
Error message
ReadResult window must satisfy 1 <= start_line <= end_line, got start_line={self.start_line}, end_line={self.end_line} What it means
ReadResult.__post_init__ enforces that the line window satisfies 1 <= start_line <= end_line. Line numbers in ReadResult are 1-based; a backend that reports start_line < 1 or an end_line before the start produces an impossible window and is rejected with a ValueError at construction. This guards downstream consumers (middleware, line-number formatting) from negative or inverted ranges.
Source
Thrown at libs/deepagents/deepagents/backends/protocol.py:268
raise ValueError(msg)
if self.no_lines_requested and (
self.error is not None or self.start_line is not None or self.next_offset is not None or self.total_lines is not None
):
msg = "ReadResult.no_lines_requested describes an uninspected window; it cannot be combined with error or pagination fields"
raise ValueError(msg)
if self.next_offset is not None and self.start_line is None:
msg = "ReadResult.next_offset requires start_line and end_line to be set"
raise ValueError(msg)
if self.total_lines is not None and self.start_line is None:
msg = "ReadResult.total_lines requires start_line and end_line to be set"
raise ValueError(msg)
# Numeric consistency of a present window. `start_line`/`end_line` are
# bound together above, so testing `start_line` covers both.
if self.start_line is not None and self.end_line is not None:
if self.start_line < 1 or self.end_line < self.start_line:
msg = f"ReadResult window must satisfy 1 <= start_line <= end_line, got start_line={self.start_line}, end_line={self.end_line}"
raise ValueError(msg)
if self.total_lines is not None and self.total_lines < self.end_line:
msg = f"ReadResult.total_lines ({self.total_lines}) cannot be less than end_line ({self.end_line})"
raise ValueError(msg)
if self.next_offset is not None and self.next_offset != self.end_line:
msg = f"ReadResult.next_offset ({self.next_offset}) must equal end_line ({self.end_line}), the 0-indexed line after the last shown"
raise ValueError(msg)
@dataclass
class WriteResult:
"""Result from backend `write` operations.
Attributes:
error: Error message on failure, `None` on success.
path: Absolute path of written file, `None` on failure.
Examples:
>>> WriteResult(path="/f.txt")View on GitHub (pinned to a1af029e6e)
Solutions
- Use 1-based numbering: start_line = offset + 1, end_line = offset + number_of_lines_returned.
- Assert in your backend that 1 <= start_line <= end_line before constructing ReadResult.
- If the result is empty, set start_line=None and end_line=None (or a valid degenerate window) rather than 0.
Example fix
// before return ReadResult(content=text, start_line=offset, end_line=offset + len(lines)) // after start = offset + 1 return ReadResult(content=text, start_line=start, end_line=start + len(lines) - 1)
Defensive patterns
Strategy: validation
Validate before calling
def check_window(start_line, end_line):
if start_line is not None and end_line is not None:
assert 1 <= start_line <= end_line, f'bad window {start_line}-{end_line}' Type guard
def has_valid_window(r) -> bool:
return r.start_line is None or (1 <= r.start_line <= (r.end_line or 0) + 1 and r.end_line >= r.start_line) Try / catch
try:
return ReadResult(content=text, start_line=start, end_line=end)
except ValueError:
return ReadResult(content=text) # degrade to unpaginated result Prevention
- Remember ReadResult line numbers are 1-based; convert the 0-based offset with offset + 1.
- Add an assertion at the end of your backend's read before constructing the result.
- Test with offset=0 specifically — it is the classic source of start_line=0 bugs.
When it happens
Trigger: Constructing ReadResult with start_line=0 (treating lines as 0-indexed), start_line=-1 (using offset directly as a 1-based line), or swapping the fields (end_line as start). E.g. ReadResult(content=t, start_line=offset, end_line=offset+limit) with offset=0.
Common situations: Confusing the backend `read(offset=...)` 0-based offset parameter with the 1-based start_line field; translating a 0-indexed slice range into the result fields without adding 1; custom backends and test fixtures.
Related errors
- ReadResult.total_lines requires start_line and end_line to b
- ReadResult.total_lines ({self.total_lines}) cannot be less t
- ReadResult.next_offset ({self.next_offset}) must equal end_l
- modes can only be provided when agent is a factory
- models can only be provided when agent is a factory
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/d712e5d1f75da7be.
Report an issue: GitHub.