HKUDS/Vibe-Trading · error · Trading212ConfigError
base_url must start with http:// or https://
Error message
base_url must start with http:// or https://
What it means
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.
Source
Thrown at agent/src/trading/connectors/trading212/sdk.py:81
"""
api_key: str = ""
api_secret: str = ""
profile: str = "live-readonly"
base_url: str = DEFAULT_BASE_URL
timeout: float = 15.0
readonly: bool = True
@classmethod
def from_mapping(cls, data: Mapping[str, Any] | None = None) -> "Trading212Config":
"""Build a config from a JSON-like mapping, normalizing profile/URL."""
payload = dict(data or {})
profile = str(payload.get("profile") or "live-readonly").strip().lower()
if profile not in PROFILE_ENVIRONMENTS:
raise Trading212ConfigError("profile must be 'paper', 'live-readonly' or 'live'")
base_url = str(payload.get("base_url") or DEFAULT_BASE_URL).strip().rstrip("/")
if not base_url.startswith(("http://", "https://")):
raise Trading212ConfigError("base_url must start with http:// or https://")
return cls(
api_key=str(payload.get("api_key") or "").strip(),
api_secret=str(payload.get("api_secret") or "").strip(),
profile=profile,
base_url=base_url,
timeout=float(payload.get("timeout") or 15.0),
readonly=bool(payload.get("readonly", True)),
)
def with_overrides(
self,
*,
api_key: str | None = None,
api_secret: str | None = None,
profile: str | None = None,
base_url: str | None = None,
) -> "Trading212Config":
"""Return a copy with CLI/tool overrides applied."""View on GitHub (pinned to 80ffdda44c)
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
Example fix
// before
{"base_url": "api.trading212.com"}
// after
{"base_url": "https://api.trading212.com"} Defensive patterns
Strategy: validation
Validate before calling
def valid_base_url(data: dict) -> bool:
url = str(data.get('base_url') or '').strip().rstrip('/')
return url.startswith(('http://', 'https://')) Type guard
def is_http_url(value: object) -> bool:
return isinstance(value, str) and value.strip().startswith(('http://', 'https://')) Try / catch
try:
cfg = Trading212Config.from_mapping(raw)
except Trading212ConfigError as exc:
if 'base_url' in str(exc):
raw.pop('base_url', None) # fall back to DEFAULT_BASE_URL
cfg = Trading212Config.from_mapping(raw)
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- profile must be 'paper', 'live-readonly' or 'live'
- group_message_buffer_size must be > 0
- SWARM_WORKER_RETRY_MAX_DELAY_S must be greater than or equal
- Unsupported config file format: {suffix or '<none>'}
- HTTP MCP servers require an explicit type of 'sse' or 'strea
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/239c9a6516f8d9ca.
Report an issue: GitHub.