odysseus-dev/odysseus · warning · HTTPException

Version not found

Error message

Version not found

What it means

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.

Source

Thrown at routes/document/document_routes.py:805

            db.close()

    # ---- GET /api/document/{doc_id}/version/{num} ----
    @router.get("/api/document/{doc_id}/version/{num}")
    async def get_version(request: Request, doc_id: str, num: int) -> Dict[str, Any]:
        user = get_current_user(request)
        db = SessionLocal()
        try:
            # Verify ownership
            doc = db.query(Document).filter(Document.id == doc_id).first()
            if not doc:
                raise HTTPException(404, "Document not found")
            _verify_doc_owner(db, doc, user)
            ver = db.query(DocumentVersion).filter(
                DocumentVersion.document_id == doc_id,
                DocumentVersion.version_number == num,
            ).first()
            if not ver:
                raise HTTPException(404, "Version not found")
            return _version_to_dict(ver)
        finally:
            db.close()

    # ---- POST /api/document/{doc_id}/restore/{num} ----
    @router.post("/api/document/{doc_id}/restore/{num}")
    async def restore_version(request: Request, doc_id: str, num: int) -> Dict[str, Any]:
        user = get_current_user(request)
        db = SessionLocal()
        try:
            doc = db.query(Document).filter(Document.id == doc_id).first()
            if not doc:
                raise HTTPException(404, "Document not found")
            _verify_doc_owner(db, doc, user)

            old_ver = db.query(DocumentVersion).filter(
                DocumentVersion.document_id == doc_id,
                DocumentVersion.version_number == num,

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. List valid version numbers first via GET /api/document/{doc_id}/versions and constrain user selection to that set.
  2. Remember version numbers are 1-based here (version_number starts at 1, restore uses version_count + 1).
  3. If racing concurrent edits, re-fetch the version list after any save/restore before requesting a specific version.

Example fix

# before
ver = requests.get(f"{base}/api/document/{doc}/version/{num}").json()

# after
versions = requests.get(f"{base}/api/document/{doc}/versions").json()
valid = {v["version_number"] for v in versions}
ver = (requests.get(f"{base}/api/document/{doc}/version/{num}").json()
        if num in valid else None)
Defensive patterns

Strategy: validation

Validate before calling

import requests

def valid_version_numbers(base: str, doc_id: str, cookies: dict) -> set:
    vs = requests.get(f"{base}/api/document/{doc_id}/versions", cookies=cookies).json()
    return {v["version_number"] for v in vs}

Try / catch

try:
    ver = requests.get(f"{base}/api/document/{doc}/version/{num}").json()
except requests.HTTPError as e:
    if e.response.status_code == 404:
        ver = pick_latest_version(doc)  # fall back to newest
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/baf201ae3c3212ce. Report an issue: GitHub.