HKUDS/Vibe-Trading · error · MT5ConfigError

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

Error message

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

What it means

MT5Config.from_mapping validates the 'profile' key and only accepts 'paper', 'live-readonly' or 'live' (case-insensitive, after strip). Any other value — or a value that normalizes to something else — raises MT5ConfigError at config-construction time, before any terminal connection is attempted.

Source

Thrown at agent/src/trading/connectors/mt5/_client.py:94

    login: int = 0
    password: str = ""
    server: str = ""
    terminal_path: str = ""
    profile: str = "paper"
    symbol_suffix: str = ""
    deviation_points: int = 20
    max_order_volume: float = 1.0
    max_order_notional_usd: float = 10_000.0
    timeout: float = 15.0
    readonly: bool = True

    @classmethod
    def from_mapping(cls, data: Mapping[str, Any] | None = None) -> "MT5Config":
        """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 MT5ConfigError("profile must be 'paper', 'live-readonly' or 'live'")
        return cls(
            login=int(payload.get("login") or 0),
            password=str(payload.get("password") or ""),
            server=str(payload.get("server") or "").strip(),
            terminal_path=str(payload.get("terminal_path") or "").strip(),
            profile=profile,
            symbol_suffix=str(payload.get("symbol_suffix") or "").strip(),
            deviation_points=int(payload.get("deviation_points") or 20),
            max_order_volume=float(payload.get("max_order_volume") or 1.0),
            max_order_notional_usd=float(payload.get("max_order_notional_usd") or 10_000.0),
            timeout=float(payload.get("timeout") or 15.0),
            readonly=bool(payload.get("readonly", True)),
        )

    def with_overrides(self, **overrides: Any) -> "MT5Config":
        """Return a copy with CLI/tool overrides applied."""
        payload = asdict(self)
        for key, value in overrides.items():

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Edit ~/.vibe-trading/mt5.json and set "profile" to one of paper, live-readonly, live
  2. If you meant a simulated account, use "paper" (not "demo")
  3. Validate config before programmatic use with MT5Config.from_mapping(raw) inside a try/except

Example fix

// before
{"profile": "demo", "login": 123}
// after
{"profile": "paper", "login": 123}
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED = {'paper', 'live-readonly', 'live'}
raw = json.loads(path.read_text())
profile = str(raw.get('profile') or 'paper').strip().lower()
assert profile in ALLOWED, f'bad profile {profile!r}'
cfg = MT5Config.from_mapping(raw)

Type guard

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

Try / catch

try:
    cfg = MT5Config.from_mapping(data)
except MT5ConfigError as e:
    # surface a config-form error to the user
    raise ValueError(f'Fix mt5.json profile: {e}') from e

Prevention

When it happens

Trigger: Loading ~/.vibe-trading/mt5.json (via load_config) or building a config with from_mapping/with_overrides/build_config where the profile field is e.g. 'demo', 'Live ', 'prod', or misspelled.

Common situations: Hand-edited mt5.json with a profile like 'demo' or 'production'; copying config from another connector that uses different profile names; trailing whitespace or wrong casing is tolerated but typos are not.

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/40b899ee382c2f14. Report an issue: GitHub.