HKUDS/Vibe-Trading · error · ValueError

outcome '{outcome}' not in {names}

Error message

outcome '{outcome}' not in {names}

What it means

Raised by prediction_market_tool._resolve_history_token when the caller passes an outcome name that doesn't case-insensitively match any entry in the market's outcomes list. The exact valid names are echoed in the message so the caller can retry with a correct one.

Source

Thrown at agent/src/tools/prediction_market_tool.py:814

    if identifier.lower().startswith("0x"):
        payload = _get_json(f"{_CLOB_MARKETS_URL}/{identifier}", host_key=_CLOB_HOST_KEY)
        raw = _clob_market_to_gamma_shape(payload) if isinstance(payload, dict) else {}
    else:
        raw = _get_json(f"{_GAMMA_MARKETS_URL}/{identifier}", host_key=_GAMMA_HOST_KEY)
        if not isinstance(raw, dict):
            raise ValueError("unexpected market payload shape")

    names = [str(n) for n in _json_list(raw.get("outcomes"))]
    tokens = [str(t) for t in _json_list(raw.get("clobTokenIds"))]
    if not tokens:
        raise ValueError("market exposes no CLOB outcome tokens")

    index = 0
    if outcome is not None:
        matches = [i for i, n in enumerate(names) if n.lower() == outcome.lower()]
        if not matches:
            raise ValueError(f"outcome '{outcome}' not in {names}")
        index = matches[0]
    if index >= len(tokens):
        raise ValueError("outcome has no matching CLOB token")

    return tokens[index], {
        "market_id": str(raw.get("id")) if raw.get("id") is not None else None,
        "question": raw.get("question"),
        "condition_id": raw.get("conditionId"),
        "outcome": names[index] if index < len(names) else None,
        "clob_token_id": tokens[index],
    }


def _fetch_history(
    identifier: str, *, interval: str, outcome: str | None, max_points: int
) -> dict[str, Any]:
    """Fetch one outcome's implied-probability time series.

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Use one of the exact names listed in the error message, matching case-insensitively
  2. Strip whitespace from the outcome string before passing it
  3. For binary markets, use the canonical 'Yes'/'No' labels
  4. Omit the outcome argument to default to index 0 (the first outcome)

Example fix

# before
outcome='yea'

# after
outcome='yes'
Defensive patterns

Strategy: validation

Validate before calling

names = [str(n) for n in market.get("outcomes", [])]
outcome = outcome.strip()
if outcome.lower() not in {n.lower() for n in names}:
    outcome = names[0]  # or raise with the valid options for the user

Type guard

def valid_outcome(outcome: str | None, names: list[str]) -> bool:
    return outcome is None or outcome.strip().lower() in {n.lower() for n in names}

Try / catch

try:
    token, meta = _resolve_history_token(identifier, outcome)
except ValueError as e:
    if "not in" in str(e):
        valid = ast.literal_eval(e.message.split("not in ")[1])
        outcome = valid[0]  # fall back to first outcome and retry

Prevention

When it happens

Trigger: Passing outcome='yes' when outcomes are ['Yes','No'] works (case-insensitive) but outcome='Y' or 'up' fails; passing an outcome to a multi-outcome market with different labels like ['Democrat','Republican','Other']; extra whitespace in the outcome string.

Common situations: LLM tool calls guessing outcome labels; users abbreviating outcome names; copy-paste adding trailing spaces; markets whose outcome vocabulary changed after a rewrite.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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