HKUDS/Vibe-Trading · error · AlpacaConfigError

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

Error message

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

What it means

Thrown by AlpacaConfig.from_mapping when the normalized 'profile' key is not one of the allowed PROFILE_ENVIRONMENTS ('paper', 'live-readonly', 'live'). The profile decides which Alpaca environment/endpoints are used, so an unrecognized value fails fast instead of defaulting to real-money trading.

Source

Thrown at agent/src/trading/connectors/alpaca/sdk.py:93

        feed: Market-data feed, ``iex`` (free) or ``sip`` (paid).
        timeout: Network timeout in seconds.
        readonly: Always true for this layer; order methods are not exposed.
    """

    api_key: str = ""
    secret_key: str = ""
    profile: str = "paper"
    feed: str = "iex"
    timeout: float = 15.0
    readonly: bool = True

    @classmethod
    def from_mapping(cls, data: Mapping[str, Any] | None = None) -> "AlpacaConfig":
        """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 AlpacaConfigError("profile must be 'paper', 'live-readonly' or 'live'")
        feed = str(payload.get("feed") or "iex").strip().lower()
        if feed not in ("iex", "sip"):
            raise AlpacaConfigError("feed must be 'iex' or 'sip'")
        return cls(
            api_key=str(payload.get("api_key") or "").strip(),
            secret_key=str(payload.get("secret_key") or "").strip(),
            profile=profile,
            feed=feed,
            timeout=float(payload.get("timeout") or 15.0),
            readonly=bool(payload.get("readonly", True)),
        )

    def with_overrides(
        self,
        *,
        api_key: str | None = None,
        secret_key: str | None = None,
        profile: str | None = None,

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Set profile to exactly 'paper', 'live-readonly', or 'live' (lowercase, hyphenated)
  2. If you intended paper trading, omit the key entirely — it defaults to 'paper'
  3. Check for stray whitespace/quotes in the JSON value (they survive strip but mismatched names do not)
  4. Upgrade to the current agent version if your config uses an older profile vocabulary

Example fix

// before
{"profile": "live_ro", "api_key": "...", "secret_key": "..."}

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

Strategy: validation

Validate before calling

VALID_PROFILES = {"paper", "live-readonly", "live"}
profile = str(cfg.get("profile") or "paper").strip().lower()
if profile not in VALID_PROFILES:
    raise ValueError(f"unknown profile {profile!r}; expected one of {sorted(VALID_PROFILES)}")

Type guard

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

Try / catch

try:
    config = AlpacaConfig.from_mapping(data)
except AlpacaConfigError as exc:
    if "profile must be" in str(exc):
        data["profile"] = "paper"
        config = AlpacaConfig.from_mapping(data)
    else:
        raise

Prevention

When it happens

Trigger: Passing a mapping (from JSON config, build_config overrides, or with_overrides) whose profile is e.g. 'production', 'LIVE!' after lowercasing still mismatches, 'live_readonly' (underscore typo), or an empty string is fine (defaults to paper) — the error needs a present-but-unknown value.

Common situations: Typos in the alpaca config file (live_ro, LIVE_READONLY); config shared from another SDK that uses 'production'/'sandbox'; old config files from a version before 'live-readonly' existed; env-var interpolation writing garbage into the profile field.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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