{"record":{"id":"239c9a6516f8d9ca","repo":"HKUDS/Vibe-Trading","slug":"base-url-must-start-with-http-or-https","errorCode":null,"errorMessage":"base_url must start with http:// or https://","messagePattern":"base_url must start with http:// or https://","errorType":"validation","errorClass":"Trading212ConfigError","httpStatus":null,"severity":"error","filePath":"agent/src/trading/connectors/trading212/sdk.py","lineNumber":81,"sourceCode":"    \"\"\"\n\n    api_key: str = \"\"\n    api_secret: str = \"\"\n    profile: str = \"live-readonly\"\n    base_url: str = DEFAULT_BASE_URL\n    timeout: float = 15.0\n    readonly: bool = True\n\n    @classmethod\n    def from_mapping(cls, data: Mapping[str, Any] | None = None) -> \"Trading212Config\":\n        \"\"\"Build a config from a JSON-like mapping, normalizing profile/URL.\"\"\"\n        payload = dict(data or {})\n        profile = str(payload.get(\"profile\") or \"live-readonly\").strip().lower()\n        if profile not in PROFILE_ENVIRONMENTS:\n            raise Trading212ConfigError(\"profile must be 'paper', 'live-readonly' or 'live'\")\n        base_url = str(payload.get(\"base_url\") or DEFAULT_BASE_URL).strip().rstrip(\"/\")\n        if not base_url.startswith((\"http://\", \"https://\")):\n            raise Trading212ConfigError(\"base_url must start with http:// or https://\")\n        return cls(\n            api_key=str(payload.get(\"api_key\") or \"\").strip(),\n            api_secret=str(payload.get(\"api_secret\") or \"\").strip(),\n            profile=profile,\n            base_url=base_url,\n            timeout=float(payload.get(\"timeout\") or 15.0),\n            readonly=bool(payload.get(\"readonly\", True)),\n        )\n\n    def with_overrides(\n        self,\n        *,\n        api_key: str | None = None,\n        api_secret: str | None = None,\n        profile: str | None = None,\n        base_url: str | None = None,\n    ) -> \"Trading212Config\":\n        \"\"\"Return a copy with CLI/tool overrides applied.\"\"\"","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/trading/connectors/trading212/sdk.py#L63-L99","documentation":"Trading212Config.from_mapping validates that base_url (after stripping trailing slashes) starts with http:// or https://. This guards the REST layer before any request is made, since a scheme-less or malformed host would otherwise fail deep inside the HTTP client with a less actionable error. Defaults to DEFAULT_BASE_URL when the key is absent.","triggerScenarios":"Calling Trading212Config.from_mapping (directly or via build_config/load_config/with_overrides) with base_url set to a scheme-less host like 'api.trading212.com', a mistyped scheme like 'ttps://...', or a template value like '${T212_URL}' that was never substituted.","commonSituations":"Env-var interpolation failing in config templates; copying a hostname from browser dev tools without the scheme; YAML config with base_url: api.trading212.com parsed as a plain string; trailing whitespace handled by strip but missing scheme not.","solutions":["Prefix the scheme: 'https://api.trading212.com' instead of 'api.trading212.com'","Remove the base_url key to fall back to DEFAULT_BASE_URL","If the value comes from a template variable, ensure substitution happened before passing the mapping to from_mapping"],"exampleFix":"// before\n{\"base_url\": \"api.trading212.com\"}\n\n// after\n{\"base_url\": \"https://api.trading212.com\"}","handlingStrategy":"validation","validationCode":"def valid_base_url(data: dict) -> bool:\n    url = str(data.get('base_url') or '').strip().rstrip('/')\n    return url.startswith(('http://', 'https://'))","typeGuard":"def is_http_url(value: object) -> bool:\n    return isinstance(value, str) and value.strip().startswith(('http://', 'https://'))","tryCatchPattern":"try:\n    cfg = Trading212Config.from_mapping(raw)\nexcept Trading212ConfigError as exc:\n    if 'base_url' in str(exc):\n        raw.pop('base_url', None)  # fall back to DEFAULT_BASE_URL\n        cfg = Trading212Config.from_mapping(raw)\n    else:\n        raise","preventionTips":["Omit base_url unless you truly need a custom host/proxy","Always include the scheme when overriding hosts; prefer https://","Assert env-var substitution completed before passing mappings to from_mapping"],"tags":["trading212","config","base-url","validation"],"backgroundTag":"invalid-url-scheme","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}