HKUDS/Vibe-Trading · error · HTTPException

str(exc)

Error message

str(exc)

What it means

After enum checks, goal_store.replace_goal can still raise ValueError for business-rule violations (e.g. non-positive token_budget/turn_budget, contradictory time_budget_seconds, or invalid objective fields); the route converts that ValueError into 400 with the exception's own message as detail. The detail string is whatever the goal store validated, so read it literally.

Source

Thrown at agent/src/api/sessions_routes.py:474

        if risk_tier is RiskTier.LIVE_TRADING_OR_EXECUTION:
            raise HTTPException(status_code=400, detail="live trading or execution goals are not supported")

        goal_store = _get_goal_store()
        try:
            goal = goal_store.replace_goal(
                session_id=session_id,
                objective=req.objective,
                criteria=criteria,
                ui_summary=req.ui_summary,
                source="api",
                protocol=req.protocol,
                risk_tier=risk_tier,
                token_budget=req.token_budget,
                turn_budget=req.turn_budget,
                time_budget_seconds=req.time_budget_seconds,
            )
        except ValueError as exc:
            raise HTTPException(status_code=400, detail=str(exc)) from exc
        snapshot = goal_store.get_goal_snapshot(goal.goal_id)
        if snapshot is None:
            raise HTTPException(status_code=500, detail="Goal created but could not be reloaded")
        svc.event_bus.emit(session_id, "goal.created", {"goal": snapshot["goal"]})
        return snapshot

    @app.get(
        "/sessions/{session_id}/goal",
        response_model=GoalSnapshotResponse,
        dependencies=[Depends(require_auth)],
    )
    async def get_session_goal(session_id: str):
        """Return the current finance research goal snapshot for a session."""
        _host_validate_path_param(session_id, "session_id")
        _get_existing_session_or_404(session_id)
        snapshot = _get_goal_store().get_current_snapshot(session_id)
        if snapshot is None:
            raise HTTPException(status_code=404, detail="No current goal")

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Read the 400 detail — it names the exact field and constraint that failed
  2. Send strictly positive budgets (token_budget>0, turn_budget>0, time_budget_seconds>0) or omit them to use defaults
  3. Pre-validate budget fields client-side before the call
  4. Check for unit mistakes, especially seconds vs minutes for time budgets

Example fix

# before
api.create_session_goal(sid, objective="o", risk_tier="LOW_RISK", token_budget=0, turn_budget=-1)  # 400 ValueError

# after
api.create_session_goal(sid, objective="o", risk_tier="LOW_RISK", token_budget=10000, turn_budget=20, time_budget_seconds=1800)
Defensive patterns

Strategy: validation

Validate before calling

def validate_goal_payload(p: dict) -> None:
    for f in ("token_budget", "turn_budget", "time_budget_seconds"):
        if f in p and p[f] is not None and p[f] <= 0:
            raise ValueError(f"{f} must be > 0")
    if not (p.get("objective") or "").strip():
        raise ValueError("objective must be non-empty")

Type guard

def is_valid_budget(v) -> TypeGuard[int]:
    return isinstance(v, int) and not isinstance(v, bool) and v > 0

Try / catch

try:
    goal = api.create_session_goal(sid, payload)
except HTTPError as e:
    if e.response.status_code == 400:
        # detail is the goal store's own ValueError message — surface it verbatim
        raise ValueError(f"Goal rejected: {e.response.json()['detail']}") from e
    raise

Prevention

When it happens

Trigger: POST /sessions/{id}/goal with negative or zero budgets (token_budget<=0, turn_budget<=0, time_budget_seconds<=0), inconsistent budget combinations, or other values rejected by the goal store's validators after the risk-tier checks pass.

Common situations: Clients copying a config template whose budgets are unset and default to 0 or -1; UI allowing empty numeric fields serialized as 0; reducing budgets during an update below the goal's already-consumed amounts; unit drifts (minutes vs seconds).

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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