HKUDS/Vibe-Trading · critical · TigerProfileMismatchError

Configured profile is live, but the account number is a…

Error message

Configured profile is live, but the account number is a 17-digit Tiger paper account. Select a paper profile for paper accounts.

What it means

The inverse of the paper mismatch: _assert_profile raises TigerProfileMismatchError when profile is 'live' but is_paper_account(account) is true, i.e. the configured account is a 17-digit paper account. This blocks code that believes it is operating on a live account from silently running against the paper environment.

Solutions

  1. If you intend paper trading, set profile back to 'paper' to match the 17-digit account
  2. If you intend live, replace account with your real live account number from the Tiger portal
  3. Keep one config file per environment to avoid half-migrated edits

Example fix

// before
{"profile": "live", "account": "20190129101234567"}  // 17-digit paper account

// after
{"profile": "paper", "account": "20190129101234567"}
Defensive patterns

Strategy: validation

Validate before calling

from agent.src.trading.connectors.tiger.sdk import is_paper_account

def live_profile_is_really_live(cfg) -> bool:
    return not (cfg.environment == 'live' and is_paper_account((cfg.account or '').strip()))

Type guard

def assert_live_not_paper(cfg: TigerConfig) -> None:
    if cfg.environment == 'live' and is_paper_account(cfg.account.strip()):
        raise ValueError('live profile configured with a paper account number')

Try / catch

try:
    place_or_read_live(cfg)
except TigerProfileMismatchError as exc:
    logger.critical('Refusing to proceed: %s', exc)
    abort_run()

Prevention

When it happens

Trigger: Any Tiger operation with profile='live' (or 'live-readonly' is not checked here — only 'live' triggers this branch) while cfg.account is a 17-digit Tiger paper account number.

Common situations: Switching a config from paper to live by editing only the profile and forgetting to update the account; reusing paper credentials after a go-live; account field populated from a paper fixture during a production deploy.

Related errors


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

Appendix: source

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

    _require_tigeropen()
    from tigeropen.quote.quote_client import QuoteClient  # type: ignore

    return QuoteClient(_client_config(cfg))


def _assert_profile(cfg: TigerConfig) -> None:
    """Fail closed when the account does not match the declared environment."""
    account = (cfg.account or "").strip()
    if not account:
        raise TigerConfigError("Tiger account number is not configured")
    paper = is_paper_account(account)
    if cfg.environment == "paper" and not paper:
        raise TigerProfileMismatchError(
            "Configured profile is paper, but the account number is not a 17-digit Tiger paper account. "
            "Use a live profile only if you intend live-account access."
        )
    if cfg.environment == "live" and paper:
        raise TigerProfileMismatchError(
            "Configured profile is live, but the account number is a 17-digit Tiger paper account. "
            "Select a paper profile for paper accounts."
        )


def _missing_fields(cfg: TigerConfig) -> list[str]:
    missing = []
    if not cfg.tiger_id:
        missing.append("tiger_id")
    if not cfg.private_key_path:
        missing.append("private_key_path")
    if not cfg.account:
        missing.append("account")
    return missing


def _public_config(cfg: TigerConfig) -> dict[str, Any]:
    """Config snapshot with credential material masked (key path only, never contents)."""

View on GitHub (pinned to 80ffdda44c)