HKUDS/Vibe-Trading · error · HTTPException

no committed mandate for {broker}

Error message

no committed mandate for {broker}

What it means

Returned as HTTP 409 by the live-runner start endpoint when no committed (authorized) trading mandate exists for the broker. Starting a persistent runner requires a prior, committed mandate; the host's _active_mandate_state(broker) returning None means authorization was never completed or was cleared.

Source

Thrown at agent/src/api/live_routes.py:987

        if not broker:
            raise HTTPException(status_code=400, detail="broker must not be blank")

        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
        )

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Complete the mandate authorization + commit flow for the broker first, then retry the start request
  2. Inspect mandate state via the mandate/authorization endpoints to confirm a committed mandate exists for that exact broker key
  3. Check that mandate persistence (state store) is reachable and was not reset between authorize and start
  4. Confirm the broker string matches the one used when the mandate was committed

Example fix

// before
POST /api/live/runner/start {"broker": "alpaca"}  // 409
// after
POST /api/live/mandate/commit {"broker": "alpaca", ...}
POST /api/live/runner/start {"broker": "alpaca"}
Defensive patterns

Strategy: validation

Validate before calling

mandate = get(f'/api/live/mandate/{broker}').json()
if mandate.get('state') != 'committed':
    commit_mandate(broker)  # run authorization/commit flow first

Try / catch

catch 409 with 'no committed mandate'; run the mandate commit flow then retry the start request once

Prevention

When it happens

Trigger: POST to start the live runner for a broker before completing the mandate authorization/commit flow; after a mandate was revoked, cleared, or never persisted for that broker.

Common situations: Fresh deployment where the operator skipped the authorization step, mandate storage reset (wiped DB/state file), or a new broker added without re-running the mandate commit flow.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/564025f55b4ea132. Report an issue: GitHub.