{"record":{"id":"fb24a6403d5a69e7","repo":"odysseus-dev/odysseus","slug":"created-document-not-found","errorCode":null,"errorMessage":"Created document not found","messagePattern":"Created document not found","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"routes/document/document_routes.py","lineNumber":310,"sourceCode":"                title=title,\n                intro_text=body_text,\n            )\n        else:\n            doc_id = create_plain_pdf_document(\n                session_id=session_id,\n                upload_id=upload_id,\n                title=title,\n                body_text=body_text,\n            )\n\n        if not doc_id:\n            raise HTTPException(500, \"Failed to create document for PDF\")\n\n        db = SessionLocal()\n        try:\n            doc = db.query(Document).filter(Document.id == doc_id).first()\n            if not doc:\n                raise HTTPException(500, \"Created document not found\")\n            # The PDF doc creators stamp owner from the session only; a\n            # session-less library import leaves owner NULL, which the Library's\n            # owner filter then hides. Stamp the requesting user so it shows.\n            if not doc.owner and user:\n                doc.owner = user\n                db.commit()\n                db.refresh(doc)\n            return _doc_to_dict(doc)\n        finally:\n            db.close()\n\n    # ---- GET /api/documents/library ----\n    @router.get(\"/api/documents/library\")\n    async def documents_library(\n        request: Request,\n        search: Optional[str] = Query(None),\n        language: Optional[str] = Query(None),\n        sort: str = Query(\"recent\"),","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/document/document_routes.py#L292-L328","documentation":"500 raised by POST /api/documents/import-pdf when the creator returned a doc_id but the immediate follow-up query db.query(Document).filter(Document.id == doc_id).first() finds no row. The document either was never committed, was rolled back, or has a different id than reported.","triggerScenarios":"The create_* helper commits on a different session/engine (e.g. its own SessionLocal bound to another DB file or schema) than the SessionLocal used for the lookup; the helper flushed but never committed and its session closed, discarding the row; a race where the row is deleted between create and read.","commonSituations":"Tests running with an in-memory SQLite DB where each SessionLocal gets a fresh database; multiple database URLs configured (dev vs prod config) so the write and read hit different databases; refactor changed the helper to use a context-managed session that rolls back on exit.","solutions":["Verify both the creator helper and this route resolve to the same database URL/engine (log the bind of each session).","With SQLite file DBs, check for a stale .db file in the working directory shadowing the expected one.","Confirm the creator helper commits before returning the id.","In tests, use a shared engine/fixture instead of per-call in-memory sessions."],"exampleFix":"# before\n# helper: s = SessionLocal(); s.add(doc); s.flush(); s.close()  # no commit -> row lost\n# after\ns = SessionLocal()\ns.add(doc)\ns.commit()\nreturn doc.id","handlingStrategy":"validation","validationCode":"def same_engine(a: Session, b: Session) -> bool:\n    return a.bind is b.bind or str(a.bind.url) == str(b.bind.url)\nassert same_engine(creator_session, SessionLocal()), 'creator and route must share one DB'","typeGuard":null,"tryCatchPattern":"try { await api.post('/api/documents/import-pdf', fd); }\ncatch (e) { if (/Created document not found/.test(e.message)) { /* env/config bug: report, don't retry */ throw new ConfigError(e.message); } throw e; }","preventionTips":["Bind all sessions to one engine in tests and production","Never mix in-memory SQLite with file-based sessions in the same process","Have creator helpers commit before returning ids"],"tags":["sqlalchemy","session","transaction","http-500","database"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}