odysseus-dev/odysseus · error · HTTPException

Source PDF {upload_id} not found in uploads

Error message

Source PDF {upload_id} not found in uploads

What it means

Raised by POST /api/document/{doc_id}/export-pdf/preview with 404 when the document references a source upload_id but _locate_current_user_upload(request, upload_id, user) cannot find that file among the current user's uploads. The document-to-PDF link exists; the underlying file does not (anymore) — deleted upload, wrong owner, or uploads directory layout changed.

Source

Thrown at routes/document/document_routes.py:1087

        any wrong values before triggering the actual download.
        """
        from src.pdf_form_doc import find_source_upload_id, parse_markdown_to_values, load_field_sidecar

        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)

            upload_id = find_source_upload_id(doc.current_content or "")
            if not upload_id:
                raise HTTPException(400, "Document is not linked to a source PDF")

            pdf_path = _locate_current_user_upload(request, upload_id, user)
            if not pdf_path:
                raise HTTPException(404, f"Source PDF {upload_id} not found in uploads")

            fields = load_field_sidecar(pdf_path)
            if not fields:
                raise HTTPException(404, "Field schema sidecar missing for source PDF")

            values = parse_markdown_to_values(doc.current_content or "")
            field_meta = {f["name"]: f for f in fields}

            preview = []
            for name, current in values.items():
                meta = field_meta.get(name)
                if not meta:
                    continue
                preview.append({
                    "name": name,
                    "label": meta.get("label") or name,
                    "type": meta.get("type"),
                    "options": meta.get("options") or [],

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Check the uploads directory for the file named by the upload_id in the error message.
  2. If the file was deleted, re-upload the same PDF so the id resolves again, or drop the export-PDF flow for this document.
  3. Align upload ownership with document ownership so the owner-scoped lookup can see the file.
  4. Exempt PDF-form source uploads from retention-based cleanup.

Example fix

# before (server)
pdf_path = _locate_current_user_upload(request, upload_id, user)
if not pdf_path:
    raise HTTPException(404, f"Source PDF {upload_id} not found in uploads")

# after (server)
pdf_path = _locate_current_user_upload(request, upload_id, user)
if not pdf_path:
    logger.warning("missing source upload %s for doc %s", upload_id, doc.id)
    raise HTTPException(404, f"Source PDF {upload_id} not found in uploads",
                        headers={"X-Reason": "upload-missing"})  # client can offer re-upload
Defensive patterns

Strategy: fallback

Validate before calling

import os

def source_upload_present(uploads_dir: str, upload_id: str, owner: str) -> bool:
    return os.path.exists(os.path.join(uploads_dir, owner, upload_id)) or \
           os.path.exists(os.path.join(uploads_dir, upload_id))

Try / catch

try:
    p = requests.post(f"{base}/api/document/{doc}/export-pdf/preview")
except requests.HTTPError as e:
    if e.response.status_code == 404 and "not found in uploads" in e.response.json().get("detail", ""):
        prompt_reupload(doc)  # file gone; re-upload restores the link
    else:
        raise

Prevention

When it happens

Trigger: The uploaded PDF was removed via an uploads-cleanup job while the derived document survived; the document belongs to another user and the ownership-scoped upload lookup excludes it; uploads stored under a different directory root than the resolver expects.

Common situations: Upload retention policy deletes files after N days; server migration moved the uploads folder; multi-user deployments where document ownership and upload ownership diverge.

Related errors


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