HKUDS/Vibe-Trading · error · TigerConfigError

profile must be 'paper', 'live-readonly' or 'live'

Error message

profile must be 'paper', 'live-readonly' or 'live'

What it means

TigerConfig.from_mapping validates the 'profile' key and rejects any value not in PROFILE_ENVIRONMENTS after normalization (strip + lowercase). Because profile defaults to 'paper' only when absent/empty, an explicitly misspelled profile string raises TigerConfigError at config-parse time, before any Tiger API call is made.

Source

Thrown at agent/src/trading/connectors/tiger/sdk.py:87

        profile: ``paper``, ``live-readonly`` or ``live``.
        timeout: Network timeout in seconds.
        readonly: Always true for this layer; order methods are not exposed.
    """

    tiger_id: str = ""
    private_key_path: str = ""
    account: str = ""
    profile: str = "paper"
    timeout: float = 15.0
    readonly: bool = True

    @classmethod
    def from_mapping(cls, data: Mapping[str, Any] | None = None) -> "TigerConfig":
        """Build a config from a JSON-like mapping, normalizing the profile."""
        payload = dict(data or {})
        profile = str(payload.get("profile") or "paper").strip().lower()
        if profile not in PROFILE_ENVIRONMENTS:
            raise TigerConfigError("profile must be 'paper', 'live-readonly' or 'live'")
        return cls(
            tiger_id=str(payload.get("tiger_id") or "").strip(),
            private_key_path=str(payload.get("private_key_path") or "").strip(),
            account=str(payload.get("account") or "").strip(),
            profile=profile,
            timeout=float(payload.get("timeout") or 15.0),
            readonly=bool(payload.get("readonly", True)),
        )

    def with_overrides(
        self,
        *,
        tiger_id: str | None = None,
        private_key_path: str | None = None,
        account: str | None = None,
        profile: str | None = None,
    ) -> "TigerConfig":
        """Return a copy with CLI/tool overrides applied."""

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Set the profile to one of the exact allowed values: 'paper', 'live-readonly', or 'live'
  2. If you intended the default, remove the profile key entirely (it defaults to 'paper')
  3. Fix typo variants like 'live_readonly' -> 'live-readonly' (hyphen, not underscore)

Example fix

// before
{"profile": "live_readonly", "tiger_id": "..."}

// after
{"profile": "live-readonly", "tiger_id": "..."}
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED = {'paper', 'live-readonly', 'live'}

profile = str(data.get('profile') or 'paper').strip().lower()
assert profile in ALLOWED, f"bad profile: {profile!r}"
cfg = TigerConfig.from_mapping(data)

Type guard

def is_valid_tiger_profile(value: object) -> bool:
    return isinstance(value, str) and value.strip().lower() in {'paper', 'live-readonly', 'live'}

Try / catch

try:
    cfg = TigerConfig.from_mapping(raw)
except TigerConfigError as exc:
    if 'profile' in str(exc):
        raw['profile'] = 'paper'  # or prompt the user
        cfg = TigerConfig.from_mapping(raw)
    else:
        raise

Prevention

When it happens

Trigger: Calling TigerConfig.from_mapping (directly or via with_overrides, build_config, load_config) with a mapping whose 'profile' is e.g. 'Paper ', 'LIVE', 'prod', 'simulation', or any non-empty string outside {'paper','live-readonly','live'}. Note whitespace and case are normalized, so only genuinely unknown values fail.

Common situations: Hand-edited JSON config with 'profile': 'demo' or 'production'; tooling writing 'live_readonly' instead of 'live-readonly'; copy-pasting profile names from Tiger docs that use different terminology.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


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