{"record":{"id":"baf201ae3c3212ce","repo":"odysseus-dev/odysseus","slug":"version-not-found","errorCode":null,"errorMessage":"Version not found","messagePattern":"Version not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"warning","filePath":"routes/document/document_routes.py","lineNumber":805,"sourceCode":"            db.close()\n\n    # ---- GET /api/document/{doc_id}/version/{num} ----\n    @router.get(\"/api/document/{doc_id}/version/{num}\")\n    async def get_version(request: Request, doc_id: str, num: int) -> Dict[str, Any]:\n        user = get_current_user(request)\n        db = SessionLocal()\n        try:\n            # Verify ownership\n            doc = db.query(Document).filter(Document.id == doc_id).first()\n            if not doc:\n                raise HTTPException(404, \"Document not found\")\n            _verify_doc_owner(db, doc, user)\n            ver = db.query(DocumentVersion).filter(\n                DocumentVersion.document_id == doc_id,\n                DocumentVersion.version_number == num,\n            ).first()\n            if not ver:\n                raise HTTPException(404, \"Version not found\")\n            return _version_to_dict(ver)\n        finally:\n            db.close()\n\n    # ---- POST /api/document/{doc_id}/restore/{num} ----\n    @router.post(\"/api/document/{doc_id}/restore/{num}\")\n    async def restore_version(request: Request, doc_id: str, num: int) -> Dict[str, Any]:\n        user = get_current_user(request)\n        db = SessionLocal()\n        try:\n            doc = db.query(Document).filter(Document.id == doc_id).first()\n            if not doc:\n                raise HTTPException(404, \"Document not found\")\n            _verify_doc_owner(db, doc, user)\n\n            old_ver = db.query(DocumentVersion).filter(\n                DocumentVersion.document_id == doc_id,\n                DocumentVersion.version_number == num,","sourceCodeStart":787,"sourceCodeEnd":823,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/document/document_routes.py#L787-L823","documentation":"Raised by GET /api/document/{doc_id}/version/{num} when the document exists and is owned by the caller, but no DocumentVersion row matches (document_id, version_number). It is a 404 meaning the requested version number is out of range — either higher than version_count or lower than the earliest stored version.","triggerScenarios":"Requesting /version/5 when the doc only has versions 1-3; racing a concurrent save that renumbers versions; requesting version 0 or a negative number via a hand-edited URL; the version row was deleted by a purge that kept only recent versions.","commonSituations":"A version-history dropdown showing stale numbers after another tab created fewer versions than expected; off-by-one errors in client code that assumes version numbers start at 0.","solutions":["List valid version numbers first via GET /api/document/{doc_id}/versions and constrain user selection to that set.","Remember version numbers are 1-based here (version_number starts at 1, restore uses version_count + 1).","If racing concurrent edits, re-fetch the version list after any save/restore before requesting a specific version."],"exampleFix":"# before\nver = requests.get(f\"{base}/api/document/{doc}/version/{num}\").json()\n\n# after\nversions = requests.get(f\"{base}/api/document/{doc}/versions\").json()\nvalid = {v[\"version_number\"] for v in versions}\nver = (requests.get(f\"{base}/api/document/{doc}/version/{num}\").json()\n        if num in valid else None)","handlingStrategy":"validation","validationCode":"import requests\n\ndef valid_version_numbers(base: str, doc_id: str, cookies: dict) -> set:\n    vs = requests.get(f\"{base}/api/document/{doc_id}/versions\", cookies=cookies).json()\n    return {v[\"version_number\"] for v in vs}","typeGuard":null,"tryCatchPattern":"try:\n    ver = requests.get(f\"{base}/api/document/{doc}/version/{num}\").json()\nexcept requests.HTTPError as e:\n    if e.response.status_code == 404:\n        ver = pick_latest_version(doc)  # fall back to newest\n    else:\n        raise","preventionTips":["Constrain version pickers to numbers from the versions list.","Re-fetch the list after concurrent saves — numbers shift.","Assume 1-based numbering, not 0-based."],"tags":["fastapi","http-404","versioning","validation"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}