odysseus-dev/odysseus · error · HTTPException
Failed to create document for PDF
Error message
Failed to create document for PDF
What it means
500 raised by POST /api/documents/import-pdf when the document-creation helper (create_form_pdf_document / create_plain_pdf_document for PDFs with form fields, or create_plain_pdf_document otherwise) returned a falsy doc_id. The PDF itself was saved successfully; only the DB insert of the Document row failed or was skipped.
Source
Thrown at routes/document/document_routes.py:304
fields = extract_fields(pdf_path)
save_field_sidecar(pdf_path, fields)
doc_id = create_form_markdown_document(
session_id=session_id,
fields=fields,
upload_id=upload_id,
title=title,
intro_text=body_text,
)
else:
doc_id = create_plain_pdf_document(
session_id=session_id,
upload_id=upload_id,
title=title,
body_text=body_text,
)
if not doc_id:
raise HTTPException(500, "Failed to create document for PDF")
db = SessionLocal()
try:
doc = db.query(Document).filter(Document.id == doc_id).first()
if not doc:
raise HTTPException(500, "Created document not found")
# The PDF doc creators stamp owner from the session only; a
# session-less library import leaves owner NULL, which the Library's
# owner filter then hides. Stamp the requesting user so it shows.
if not doc.owner and user:
doc.owner = user
db.commit()
db.refresh(doc)
return _doc_to_dict(doc)
finally:
db.close()
# ---- GET /api/documents/library ----View on GitHub (pinned to f9235ebbf1)
Solutions
- Check server logs for any error/warning from the create_*_pdf_document helper just before the 500.
- Reproduce with session_id supplied vs omitted to see which code path (form vs plain) returns None.
- Read create_form_pdf_document / create_plain_pdf_document and find every `return None` branch — fix or log the branch taken.
- If the None return hides an exception, let it propagate (or raise HTTPException) instead of returning None.
Example fix
# before
doc_id = create_plain_pdf_document(...) # returns None on internal error, endpoint 500s opaquely
# after
# in the helper: raise/log the cause, or in the route:
if not doc_id:
logger.error(f"pdf doc creator returned None for upload {upload_id} (form={is_form})")
raise HTTPException(500, "Failed to create document for PDF") Defensive patterns
Strategy: try-catch
Try / catch
try { const r = await api.post('/api/documents/import-pdf', fd); }
catch (e) {
if (/Failed to create document for PDF/.test(e.message)) {
// PDF stored but DB row not created — do not re-upload the same file blindly
notify('Import failed at document creation; contact support with the upload id');
} else throw e;
} Prevention
- Ensure session_id passed to import matches an existing session
- Server-side: make create_* helpers raise instead of returning None
- Watch logs for the form-PDF code path when supporting AcroForm imports
When it happens
Trigger: The PDF is a form (has_form_fields true) and create_form_pdf_document hits an internal error and returns None; create_plain_pdf_document returns None because session_id points to a session its own check rejects; DB constraint failure inside the creator that is swallowed and converted to a None return.
Common situations: Importing a session-less PDF while the creator helper secretly requires a session; AcroForm PDFs exercising the form-document code path for the first time; creator helpers that catch exceptions broadly and return None, hiding the real error.
Related errors
- Failed to delete calendar
- Failed to list calendars
- Failed to list events
- Failed to create event
- Failed to update event
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/cb0a322f8e11983c.
Report an issue: GitHub.