odysseus-dev/odysseus · error · HTTPException

Failed to fetch document library: {e}

Error message

Failed to fetch document library: {e}

What it means

Generic 500 wrapper around GET /api/documents/library: any unexpected exception while building the library listing (query construction, iteration over docs, or serialization such as .isoformat() on timestamps) is caught, logged as 'Failed to fetch document library: <e>', and re-raised as 500 after db.close().

Source

Thrown at routes/document/document_routes.py:440

                    "session_id": doc.session_id,
                    "session_name": session_name,
                    "title": doc.title,
                    "language": _library_language_for_document(doc),
                    "preview": (doc.current_content or "")[:500],
                    "version_count": doc.version_count,
                    "created_at": (doc.created_at.isoformat() + "Z") if doc.created_at else None,
                    "updated_at": (doc.updated_at.isoformat() + "Z") if doc.updated_at else None,
                })

            return {
                "documents": documents,
                "total": total,
                "languages": languages,
                "session_count": session_count,
            }
        except Exception as e:
            logger.error(f"Failed to fetch document library: {e}")
            raise HTTPException(500, f"Failed to fetch document library: {e}")
        finally:
            db.close()

    # ---- GET /api/documents/{session_id} ----
    @router.get("/api/documents/{session_id}")
    async def list_documents(request: Request, session_id: str) -> List[Dict[str, Any]]:
        user = get_current_user(request)
        db = SessionLocal()
        try:
            if not user:
                if not _auth_disabled():
                    raise HTTPException(403, "Authentication required")
            # v2 review HIGH-9: raise 403 explicitly when the caller
            # can't see this session, instead of returning [] which the
            # UI treats identically to "no docs" and silently masks
            # auth failures.
            _get_session_or_404(db, session_id, user)
            q = db.query(Document).filter(

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Read the logged exception after 'Failed to fetch document library:' — it names the exact failing column or call.
  2. If it is AttributeError on None timestamps, backfill NULL created_at/updated_at values or guard them (the code already guards with if doc.created_at — check the other fields in the dict block).
  3. If it is OperationalError: database is locked, reduce concurrent writers or move to a proper RDBMS.
  4. Run the project's migration so all columns referenced by the serializer exist.

Example fix

# before
"created_at": doc.created_at.isoformat() + "Z"  # crashes on legacy NULL rows
# after
"created_at": (doc.created_at.isoformat() + "Z") if doc.created_at else None
Defensive patterns

Strategy: try-catch

Try / catch

try { const lib = await api.get('/api/documents/library'); }
catch (e) {
  if (e.status === 500 && /document library/.test(e.message)) {
    notify('Library temporarily unavailable'); // safe to retry after a delay
    await delay(2000); return api.get('/api/documents/library');
  }
  throw e;
}

Prevention

When it happens

Trigger: A row with corrupt/None created_at or updated_at hitting code that assumes a datetime; a DB connectivity failure mid-query; schema drift (selected column missing); an exception inside the per-doc dict building block shown above the handler.

Common situations: Older rows predating a migration that added timestamp columns (values NULL where code calls a method unconditionally); database locked by another writer in SQLite; upgrading the app without migrating data.

Related errors


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