odysseus-dev/odysseus · error · HTTPException

No endpoint configured for AI tidy

Error message

No endpoint configured for AI tidy

What it means

Raised by POST /api/documents/ai-tidy when neither resolve_task_endpoint(owner=user) nor the fallback resolve_endpoint('default', owner=user) returns both a url and a model. It is a configuration 500: the AI-classification step cannot run because no LLM endpoint is registered for this owner (or globally as default).

Source

Thrown at routes/document/document_routes.py:981

        finally:
            db.close()

    # ---- POST /api/documents/ai-tidy — AI-powered cleanup of junk/test documents ----
    @router.post("/api/documents/ai-tidy")
    async def ai_tidy_documents(request: Request) -> Dict[str, Any]:
        """Use AI to judge if documents are junk/test/accidental, then delete them.
        Caches verdicts so previously-reviewed docs are skipped."""
        from src.task_endpoint import resolve_task_endpoint
        from src.endpoint_resolver import resolve_endpoint
        from src.llm_core import llm_call_async

        user = get_current_user(request)
        url, model, headers = resolve_task_endpoint(owner=user or None)
        if not url or not model:
            # Fall back to default endpoint
            url, model, headers = resolve_endpoint("default", owner=user or None)
        if not url or not model:
            raise HTTPException(500, "No endpoint configured for AI tidy")

        db = SessionLocal()
        try:
            q = (
                db.query(Document)
                .outerjoin(DbSession, Document.session_id == DbSession.id)
                .filter(Document.is_active == True)
                .filter((Document.archived == False) | (Document.archived.is_(None)))
            )
            q = _owner_session_filter(q, user)
            docs = q.all()

            # Only review docs that haven't been reviewed yet
            to_review = [d for d in docs if not d.tidy_verdict]
            if not to_review:
                return {"deleted": 0, "reviewed": 0, "message": "All documents already reviewed"}

            # Build a batch prompt — review up to 30 at a time

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Configure a task/default endpoint via the app's endpoint settings UI or resolver config so resolve_endpoint('default') returns url+model.
  2. Verify the owner scoping: either set a default endpoint that applies to all users or one bound to the calling user.
  3. Confirm both url AND model are non-empty — the check fails if either is blank.
  4. As a fallback, use POST /api/documents/tidy (non-AI) which needs no endpoint.

Example fix

# before
resp = requests.post(f"{base}/api/documents/ai-tidy")  # 500 if unconfigured

# after
url, model, _ = resolve_endpoint("default", owner=user or None)
if not url or not model:
    resp = requests.post(f"{base}/api/documents/tidy")  # heuristic cleanup instead
else:
    resp = requests.post(f"{base}/api/documents/ai-tidy")
Defensive patterns

Strategy: validation

Validate before calling

url, model, _ = resolve_endpoint("default", owner=user or None)
if not url or not model:
    use_plain_tidy = True  # no AI endpoint configured

Try / catch

try:
    r = requests.post(f"{base}/api/documents/ai-tidy")
except requests.HTTPError as e:
    if e.response.status_code == 500 and "No endpoint configured" in e.response.json().get("detail", ""):
        r = requests.post(f"{base}/api/documents/tidy")  # non-AI fallback
    else:
        raise

Prevention

When it happens

Trigger: Calling ai-tidy on a fresh install where no endpoints are configured; the user-specific endpoint row exists but has an empty model field; endpoint config was cleared or its owner scope does not cover the current user; running under a service account with no default endpoint.

Common situations: New deployment before provider keys/endpoints are entered; per-user endpoint settings partially saved (url set, model blank); environment-specific config not migrated to production.

Related errors


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