langchain-ai/deepagents · error · ValueError
ReadResult.next_offset ({self.next_offset}) must equal end_l
Error message
ReadResult.next_offset ({self.next_offset}) must equal end_line ({self.end_line}), the 0-indexed line after the last shown What it means
ReadResult.__post_init__ requires that when next_offset is present it equals end_line exactly. The protocol defines next_offset as the 0-indexed position of the line after the last shown line, which is numerically the same as the 1-based end_line. A mismatch means the backend invented a different continuation convention and the result is rejected with a ValueError.
Source
Thrown at libs/deepagents/deepagents/backends/protocol.py:274
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")
>>> WriteResult(error="File exists")
"""
error: str | None = None
path: str | None = None
View on GitHub (pinned to a1af029e6e)
Solutions
- Set next_offset = end_line whenever a continuation offset is needed.
- Derive next_offset from end_line rather than computing it from the raw offset/limit inputs.
- Omit next_offset when there is no meaningful continuation; it is optional.
Example fix
// before return ReadResult(content=text, start_line=1, end_line=50, next_offset=51) // after return ReadResult(content=text, start_line=1, end_line=50, next_offset=50)
Defensive patterns
Strategy: validation
Validate before calling
def check_next_offset(end_line, next_offset):
if next_offset is not None and end_line is not None:
assert next_offset == end_line, f'next_offset must equal end_line, got {next_offset}' Type guard
def has_valid_next_offset(r) -> bool:
return r.next_offset is None or r.end_line is None or r.next_offset == r.end_line Try / catch
try:
result = ReadResult(..., end_line=end, next_offset=nxt)
except ValueError:
result = ReadResult(..., end_line=end, next_offset=end) Prevention
- Derive next_offset from end_line, never compute it independently from offset/limit.
- Remember the convention: next_offset is 0-indexed (the line after the last shown), which numerically equals the 1-based end_line.
- Omit next_offset if you are unsure; it is optional.
When it happens
Trigger: Constructing ReadResult with next_offset = end_line + 1 (treating next_offset as 1-based), next_offset = start of next page computed independently of end_line, or next_offset set from the byte offset instead of the line offset.
Common situations: Custom backends adapting from other pagination APIs (byte-offset or 1-based page cursors); hand-built results in tests; code updated after the protocol unified next_offset with end_line.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- ReadResult.total_lines ({self.total_lines}) cannot be less t
- ReadResult.total_lines requires start_line and end_line to b
- ReadResult window must satisfy 1 <= start_line <= end_line,
- 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/f947c67042072c67.
Report an issue: GitHub.