HKUDS/Vibe-Trading · error · HTTPException
mandate for {broker} has expired; re-authorize first
Error message
mandate for {broker} has expired; re-authorize first What it means
HTTP 409 from the live-runner start endpoint: a mandate for the broker exists but mandate.expired is True. Mandates have a bounded validity window; an expired mandate cannot drive a runner and must be re-authorized before starting.
Source
Thrown at agent/src/api/live_routes.py:989
if not broker_supports_live_runner(broker):
raise HTTPException(
status_code=400,
detail=f"live runner is not supported for {broker}",
)
h = _host()
tasks = h._runner_tasks
existing = tasks.get(broker)
if existing is not None and not existing.done():
return {"broker": broker, "started": False, "already_running": True}
mandate = h._active_mandate_state(broker)
if mandate is None:
raise HTTPException(status_code=409, detail=f"no committed mandate for {broker}")
if mandate.expired:
raise HTTPException(status_code=409, detail=f"mandate for {broker} has expired; re-authorize first")
if halt_flag_set(broker=broker) or halt_flag_set(broker=None):
raise HTTPException(status_code=409, detail="kill switch is tripped; resume before starting the runner")
try:
runner = h._build_live_runner(broker)
except LiveRunnerUnavailable as exc:
raise HTTPException(status_code=503, detail=str(exc)) from exc
except Exception as exc:
raise HTTPException(status_code=500, detail=f"could not construct runner: {exc}") from exc
task = asyncio.ensure_future(h._drive_runner(runner))
tasks[broker] = task
task.add_done_callback(
lambda t, b=broker: tasks.pop(b, None) if tasks.get(b) is t else None
)
h._emit_live_event(
payload.session_id,View on GitHub (pinned to 80ffdda44c)
Solutions
- Re-run the mandate authorization/commit flow for the broker to get a fresh, unexpired mandate, then retry start
- Check server clock sync (NTP) if the mandate should still be valid
- Consider requesting a longer mandate validity window when authorizing if expiries are frequent
Example fix
// before
POST /api/live/runner/start {"broker": "alpaca"} // 409 mandate expired
// after
POST /api/live/mandate/commit {"broker": "alpaca", ...}
POST /api/live/runner/start {"broker": "alpaca"} Defensive patterns
Strategy: retry
Validate before calling
m = get(f'/api/live/mandate/{broker}').json()
from datetime import datetime, timezone
if datetime.fromisoformat(m['expires_at']) < datetime.now(timezone.utc):
commit_mandate(broker) # re-authorize Try / catch
catch 409 with 'has expired'; re-run authorization/commit, then retry start exactly once
Prevention
- Track mandate expiry client-side and re-authorize proactively before TTL
- Keep server clocks NTP-synced
When it happens
Trigger: POST to start the runner for a broker whose committed mandate's expiry timestamp has passed — e.g. a long-lived runner restarted after the mandate TTL elapsed.
Common situations: Restarting runners after maintenance windows or downtime, long TTL gaps overnight, or clock skew between the mandate issuer and the API host causing premature expiry.
Related errors
- no committed mandate for {broker}
- no MCP server configured for live broker {broker!r}
- live runner for {broker!r} does not define remote tool {oper
- live runner is not supported for {broker}
- live trading or execution goals are not supported
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/f8461009a19d1e8d.
Report an issue: GitHub.