odysseus-dev/odysseus · error · HTTPException
Email integration is not available
Error message
Email integration is not available
What it means
Raised as HTTP 503 by GET /api/codex/emails when email_list_endpoint is None — setup_codex_routes failed to find the endpoint for GET /api/email/list on the email router passed to it. The codex surface is a proxy over the core email integration; if the underlying router was not wired (or its route path/method changed), the proxy reports service-unavailable rather than crashing.
Source
Thrown at routes/codex_routes.py:264
owner = _scope_owner(request, allowed)
args = dict(body)
args["action"] = action
return await do_manage_notes(json.dumps(args), owner=owner)
@router.get("/emails")
async def list_emails(
request: Request,
folder: str = "INBOX",
limit: int = 10,
offset: int = 0,
filter: str = "all",
from_addr: str | None = None,
account_id: str | None = None,
has_attachments: int = 0,
):
owner = _scope_owner(request, EMAIL_READ_SCOPES)
if email_list_endpoint is None:
raise HTTPException(503, "Email integration is not available")
limit = max(1, min(int(limit or 10), 50))
offset = max(0, int(offset or 0))
if account_id:
from routes.email_helpers import _assert_owns_account
_assert_owns_account(account_id, owner)
return await email_list_endpoint(
folder=folder,
limit=limit,
offset=offset,
filter=filter,
from_addr=from_addr,
account_id=account_id,
has_attachments=has_attachments,
cache_bust=None,
owner=owner,
)
View on GitHub (pinned to f9235ebbf1)
Solutions
- Confirm the email integration is enabled and its router is registered — hit GET /api/email/list directly; if that 404s too, the integration is not mounted.
- Check the call site of setup_codex_routes to ensure email_router is passed and non-None.
- Align versions: upgrade so codex_routes' _find_endpoint path matches the current email router layout.
- Re-enable the email feature flag / dependency (e.g. installed mail provider) and restart.
Example fix
# before app.include_router(setup_codex_routes(email_router=None, ...)) # after from routes.email_routes import build_email_router app.include_router(setup_codex_routes(email_router=build_email_router(), ...))
Defensive patterns
Strategy: validation
Validate before calling
async function codexEmailsReady() {
const core = await fetch('/api/email/list?limit=1');
return core.ok; // if core email API is dead, codex proxy will 503
} Try / catch
try { r = await codexListEmails() } catch (e) { if (e.status === 503) { disableEmailFeatures(); notify('Email integration not available') } else throw } Prevention
- Probe the core integration endpoint once at startup and disable dependent UI on failure.
- Guarantee setup_codex_routes always receives built routers — assert non-None in tests.
- Treat 503 from codex routes as configuration drift, not transient: do not blind-retry.
When it happens
Trigger: Calling /api/codex/emails when setup_codex_routes was invoked with email_router=None, an empty router, or one whose /api/email/list route was renamed/removed in a newer version.
Common situations: Email integration disabled at startup by config; version skew where codex_routes looks up an old email route path; a custom app.py that forgets to pass the email router into setup_codex_routes.
Related errors
- Documents integration is not available
- Invalid draft payload: {exc}
- HTTP ${res.status}
- data.error || 'failed'
- data.error
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/fb113164ce30a978.
Report an issue: GitHub.