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.
Solutions
- Read the 400 detail — it names the exact field and constraint that failed
- Send strictly positive budgets (token_budget>0, turn_budget>0, time_budget_seconds>0) or omit them to use defaults
- Pre-validate budget fields client-side before the call
- 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
- Validate budgets positive and objective non-empty client-side
- Read the 400 detail literally — it names the offending field
- Omit optional budgets instead of sending 0/placeholder values
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
- invalid risk_tier
- live trading or execution goals are not supported
- live runner is not supported for
- alpha_id and zoo are mutually exclusive
- alpha_id not found
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/05758ead7722b21a.
Report an issue: GitHub.
Appendix: 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)