odysseus-dev/odysseus · warning · HTTPException

No documents found

Error message

No documents found

What it means

404 from POST /api/documents/export-zip: ids were supplied, but after querying and filtering the documents the loop wrote zero entries into the zip (wrote == 0). Typically the ids do not match any Document rows (deleted, wrong user's docs) — a partial match writes some files and does not raise.

Source

Thrown at routes/document/document_routes.py:608

            with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf:
                for doc in docs:
                    try:
                        _verify_doc_owner(db, doc, user)
                    except HTTPException:
                        continue   # skip docs the user doesn't own
                    ext = _ext.get(doc.language or "text", ".txt")
                    base = (doc.title or "document").strip() or "document"
                    base = re.sub(r"[^\w\-. ]+", "", base)[:60].strip() or doc.id
                    name = base if "." in base else base + ext
                    i = 1
                    while name in used:
                        name = f"{base}-{i}" + ("" if "." in base else ext)
                        i += 1
                    used.add(name)
                    zf.writestr(name, doc.current_content or "")
                    wrote += 1
            if not wrote:
                raise HTTPException(404, "No documents found")
            return Response(
                content=buf.getvalue(),
                media_type="application/zip",
                headers={"Content-Disposition": 'attachment; filename="documents.zip"'},
            )
        finally:
            db.close()

    # ---- PUT /api/document/{doc_id} — user manual edit ----
    # Coalesce window: if the last user version was saved within this many
    # seconds, update it in-place (user is still actively editing).
    # Once the gap exceeds this, the next save creates a new version.
    VERSION_COALESCE_SECONDS = 60

    @router.put("/api/document/{doc_id}")
    async def update_document(request: Request, doc_id: str, req: DocumentUpdate) -> Dict[str, Any]:
        user = get_current_user(request)
        db = SessionLocal()

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Re-fetch GET /api/documents/library and export ids that currently exist for this user.
  2. Trim/normalize ids before sending; drop falsy entries.
  3. Treat 404 here as 'selection is stale' and prompt a refresh rather than retrying the same ids.

Example fix

// before
await api.post('/api/documents/export-zip', { ids: selectionFromLastHour }); // 404
// after
const live = (await api.get('/api/documents/library')).documents.map(d => d.id);
const ids = selection.filter(id => live.includes(id));
if (ids.length) await api.post('/api/documents/export-zip', { ids });
Defensive patterns

Strategy: validation

Validate before calling

const live = new Set((await api.get('/api/documents/library')).documents.map(d => d.id));
const ids = requestedIds.map(s => s.trim()).filter(id => live.has(id));
if (!ids.length) { refreshLibrary(); return; }

Try / catch

try { return await api.post('/api/documents/export-zip', { ids }); }
catch (e) { if (e.status === 404 && /No documents found/.test(e.message)) { await refreshLibrary(); return null; } throw e; }

Prevention

When it happens

Trigger: All requested ids are stale/deleted; ids belong to another owner and are filtered out; ids with whitespace or case differences that fail the equality match; empty strings in the ids array.

Common situations: Exporting a selection made before another session deleted those docs; shared id lists between users; copy-paste artifacts in ids.

Related errors


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