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

  1. Prefix the scheme: 'https://api.trading212.com' instead of 'api.trading212.com'
  2. Remove the base_url key to fall back to DEFAULT_BASE_URL
  3. 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

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


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