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 timeView on GitHub (pinned to f9235ebbf1)
Solutions
- Configure a task/default endpoint via the app's endpoint settings UI or resolver config so resolve_endpoint('default') returns url+model.
- Verify the owner scoping: either set a default endpoint that applies to all users or one bound to the calling user.
- Confirm both url AND model are non-empty — the check fails if either is blank.
- 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
- Configure a default LLM endpoint (url AND model) before enabling ai-tidy.
- Preflight-check endpoint config in the UI and gray out AI tidy when missing.
- Remember per-user endpoints need the owner scope to match the caller.
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 tidy failed: {e}
- Upload handler not configured
- Tidy failed: {e}
- AI returned invalid response
- Failed to delete calendar
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/83adb527da899b02.
Report an issue: GitHub.