{"record":{"id":"70bf7cbdf8a297b7","repo":"langchain-ai/deepagents","slug":"readresult-total-lines-self-total-lines-cannot","errorCode":null,"errorMessage":"ReadResult.total_lines ({self.total_lines}) cannot be less than end_line ({self.end_line})","messagePattern":"ReadResult\\.total_lines \\((.+?)\\) cannot be less than end_line \\((.+?)\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/backends/protocol.py","lineNumber":271,"sourceCode":"        ):\n            msg = \"ReadResult.no_lines_requested describes an uninspected window; it cannot be combined with error or pagination fields\"\n            raise ValueError(msg)\n        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","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/backends/protocol.py#L253-L289","documentation":"ReadResult.__post_init__ requires that when both the window and total_lines are present, total_lines >= end_line. The last line shown cannot be beyond the end of the file, so a result claiming, say, end_line=50 of a file with total_lines=30 is internally inconsistent and rejected with a ValueError. This keeps pagination invariants (total covers the window) intact for consumers.","triggerScenarios":"Constructing ReadResult where total_lines is computed from a truncated/partial count while end_line reflects a larger window — e.g. counting only the lines in the returned content instead of the whole file, or hardcoding a stale total after the file shrank.","commonSituations":"Custom backends computing total_lines from len(content.splitlines()) of the returned window instead of the full file; caching total counts across edits; unit-test fixtures with mismatched numbers.","solutions":["Compute total_lines from the full file (all lines), not just the returned window.","Clamp or recompute end_line so it never exceeds total_lines when the requested window runs past EOF.","Omit total_lines if the backend cannot reliably determine the full line count."],"exampleFix":"// before\nreturn ReadResult(content=text, start_line=1, end_line=len(lines), total_lines=len(lines))\n// after\nall_lines = full_file_text.splitlines()\nreturn ReadResult(content=text, start_line=1, end_line=len(lines), total_lines=len(all_lines))","handlingStrategy":"validation","validationCode":"def check_total(end_line, total_lines):\n    if total_lines is not None and end_line is not None:\n        assert total_lines >= end_line, f'total_lines={total_lines} < end_line={end_line}'","typeGuard":"def has_consistent_total(r) -> bool:\n    return r.total_lines is None or r.end_line is None or r.total_lines >= r.end_line","tryCatchPattern":"try:\n    result = ReadResult(..., total_lines=total)\nexcept ValueError:\n    result = ReadResult(...)  # retry without total_lines","preventionTips":["Compute total_lines from the full file content, never from the returned window.","Clamp end_line to total_lines when a requested window extends past EOF.","Avoid caching total line counts across writes/edits to the same file."],"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"}