{"record":{"id":"f947c67042072c67","repo":"langchain-ai/deepagents","slug":"readresult-next-offset-self-next-offset-must-e","errorCode":null,"errorMessage":"ReadResult.next_offset ({self.next_offset}) must equal end_line ({self.end_line}), the 0-indexed line after the last shown","messagePattern":"ReadResult\\.next_offset \\((.+?)\\) must equal end_line \\((.+?)\\), the 0-indexed line after the last shown","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/backends/protocol.py","lineNumber":274,"sourceCode":"        if self.next_offset is not None and self.start_line is None:\n            msg = \"ReadResult.next_offset requires start_line and end_line to be set\"\n            raise ValueError(msg)\n        if self.total_lines is not None and self.start_line is None:\n            msg = \"ReadResult.total_lines requires start_line and end_line to be set\"\n            raise ValueError(msg)\n\n        # Numeric consistency of a present window. `start_line`/`end_line` are\n        # bound together above, so testing `start_line` covers both.\n        if self.start_line is not None and self.end_line is not None:\n            if self.start_line < 1 or self.end_line < self.start_line:\n                msg = f\"ReadResult window must satisfy 1 <= start_line <= end_line, got start_line={self.start_line}, end_line={self.end_line}\"\n                raise ValueError(msg)\n            if self.total_lines is not None and self.total_lines < self.end_line:\n                msg = f\"ReadResult.total_lines ({self.total_lines}) cannot be less than end_line ({self.end_line})\"\n                raise ValueError(msg)\n            if self.next_offset is not None and self.next_offset != self.end_line:\n                msg = f\"ReadResult.next_offset ({self.next_offset}) must equal end_line ({self.end_line}), the 0-indexed line after the last shown\"\n                raise ValueError(msg)\n\n\n@dataclass\nclass WriteResult:\n    \"\"\"Result from backend `write` operations.\n\n    Attributes:\n        error: Error message on failure, `None` on success.\n        path: Absolute path of written file, `None` on failure.\n\n    Examples:\n        >>> WriteResult(path=\"/f.txt\")\n        >>> WriteResult(error=\"File exists\")\n    \"\"\"\n\n    error: str | None = None\n    path: str | None = None\n","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/backends/protocol.py#L256-L292","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nreturn ReadResult(content=text, start_line=1, end_line=50, next_offset=51)\n// after\nreturn ReadResult(content=text, start_line=1, end_line=50, next_offset=50)","handlingStrategy":"validation","validationCode":"def check_next_offset(end_line, next_offset):\n    if next_offset is not None and end_line is not None:\n        assert next_offset == end_line, f'next_offset must equal end_line, got {next_offset}'","typeGuard":"def has_valid_next_offset(r) -> bool:\n    return r.next_offset is None or r.end_line is None or r.next_offset == r.end_line","tryCatchPattern":"try:\n    result = ReadResult(..., end_line=end, next_offset=nxt)\nexcept ValueError:\n    result = ReadResult(..., end_line=end, next_offset=end)","preventionTips":["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."],"tags":["validation","pagination","backend-protocol"],"backgroundTag":"schema-validation-failed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}