{"record":{"id":"40b899ee382c2f14","repo":"HKUDS/Vibe-Trading","slug":"profile-must-be-paper-live-readonly-or-live-40b899","errorCode":null,"errorMessage":"profile must be 'paper', 'live-readonly' or 'live'","messagePattern":"profile must be 'paper', 'live-readonly' or 'live'","errorType":"validation","errorClass":"MT5ConfigError","httpStatus":null,"severity":"error","filePath":"agent/src/trading/connectors/mt5/_client.py","lineNumber":94,"sourceCode":"    login: int = 0\n    password: str = \"\"\n    server: str = \"\"\n    terminal_path: str = \"\"\n    profile: str = \"paper\"\n    symbol_suffix: str = \"\"\n    deviation_points: int = 20\n    max_order_volume: float = 1.0\n    max_order_notional_usd: float = 10_000.0\n    timeout: float = 15.0\n    readonly: bool = True\n\n    @classmethod\n    def from_mapping(cls, data: Mapping[str, Any] | None = None) -> \"MT5Config\":\n        \"\"\"Build a config from a JSON-like mapping, normalizing the profile.\"\"\"\n        payload = dict(data or {})\n        profile = str(payload.get(\"profile\") or \"paper\").strip().lower()\n        if profile not in PROFILE_ENVIRONMENTS:\n            raise MT5ConfigError(\"profile must be 'paper', 'live-readonly' or 'live'\")\n        return cls(\n            login=int(payload.get(\"login\") or 0),\n            password=str(payload.get(\"password\") or \"\"),\n            server=str(payload.get(\"server\") or \"\").strip(),\n            terminal_path=str(payload.get(\"terminal_path\") or \"\").strip(),\n            profile=profile,\n            symbol_suffix=str(payload.get(\"symbol_suffix\") or \"\").strip(),\n            deviation_points=int(payload.get(\"deviation_points\") or 20),\n            max_order_volume=float(payload.get(\"max_order_volume\") or 1.0),\n            max_order_notional_usd=float(payload.get(\"max_order_notional_usd\") or 10_000.0),\n            timeout=float(payload.get(\"timeout\") or 15.0),\n            readonly=bool(payload.get(\"readonly\", True)),\n        )\n\n    def with_overrides(self, **overrides: Any) -> \"MT5Config\":\n        \"\"\"Return a copy with CLI/tool overrides applied.\"\"\"\n        payload = asdict(self)\n        for key, value in overrides.items():","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/trading/connectors/mt5/_client.py#L76-L112","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Edit ~/.vibe-trading/mt5.json and set \"profile\" to one of paper, live-readonly, live","If you meant a simulated account, use \"paper\" (not \"demo\")","Validate config before programmatic use with MT5Config.from_mapping(raw) inside a try/except"],"exampleFix":"// before\n{\"profile\": \"demo\", \"login\": 123}\n// after\n{\"profile\": \"paper\", \"login\": 123}","handlingStrategy":"validation","validationCode":"ALLOWED = {'paper', 'live-readonly', 'live'}\nraw = json.loads(path.read_text())\nprofile = str(raw.get('profile') or 'paper').strip().lower()\nassert profile in ALLOWED, f'bad profile {profile!r}'\ncfg = MT5Config.from_mapping(raw)","typeGuard":"def is_valid_mt5_profile(v: object) -> bool:\n    return isinstance(v, str) and v.strip().lower() in {'paper','live-readonly','live'}","tryCatchPattern":"try:\n    cfg = MT5Config.from_mapping(data)\nexcept MT5ConfigError as e:\n    # surface a config-form error to the user\n    raise ValueError(f'Fix mt5.json profile: {e}') from e","preventionTips":["Generate config only through save_config / typed forms, never hand-edit JSON","Validate profile against the allowed set before persisting","Add a config schema check to your deploy pipeline"],"tags":["mt5","config","validation","profile"],"backgroundTag":"invalid-config-value","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}