{"record":{"id":"c4674138c8859998","repo":"unslothai/unsloth","slug":"provider-base-url-must-use-http-or-https","errorCode":null,"errorMessage":"Provider base URL must use http or https.","messagePattern":"Provider base URL must use http or https\\.","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"studio/backend/core/inference/providers.py","lineNumber":885,"sourceCode":"    before), so validating an already-validated URL returns it unchanged.\n    \"\"\"\n    if not isinstance(base_url, str) or not base_url.strip():\n        raise ValueError(\"Provider base URL is required.\")\n\n    raw = base_url.strip()\n    if any(char.isspace() or ord(char) < 32 or ord(char) == 127 for char in raw) or \"\\\\\" in raw:\n        raise ValueError(\"Provider base URL contains invalid characters.\")\n\n    try:\n        parts = urlsplit(raw)\n        port = parts.port\n        hostname = parts.hostname\n    except ValueError as exc:\n        raise ValueError(\"Provider base URL is malformed.\") from exc\n\n    scheme = parts.scheme.lower()\n    if scheme not in (\"http\", \"https\"):\n        raise ValueError(\"Provider base URL must use http or https.\")\n    # Userinfo stays allowed for gateways behind basic auth; the checks below read\n    # the parsed hostname, so http://api.openai.com@169.254.169.254/ is caught.\n    if not hostname:\n        raise ValueError(\"Provider base URL must contain a hostname.\")\n\n    hostname = hostname.rstrip(\".\")\n    if _metadata_host(hostname) or _resolves_to_metadata(hostname, port, scheme):\n        raise ValueError(\"Cloud metadata endpoints cannot be used as a provider base URL.\")\n\n    if os.environ.get(_BLOCK_PRIVATE_ENV) == \"1\":\n        _reject_non_public(hostname, port, scheme)\n\n    return raw.rstrip(\"/\")\n\n\ndef list_available_providers(include_hidden: bool = False) -> list[dict[str, Any]]:\n    \"\"\"Return registered providers (for the /registry endpoint).\n","sourceCodeStart":867,"sourceCodeEnd":903,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/providers.py#L867-L903","documentation":"The URL parsed successfully but its lowercased scheme is neither http nor https. The backend only issues plain HTTP requests to provider endpoints, so any other scheme (ftp, file, websocket, or a missing scheme making the host parse as one) is refused.","triggerScenarios":"Passing 'ftp://host/model', 'file:///etc/passwd', a bare 'api.openai.com/v1' (parsed with 'api.openai.com' as scheme), or 'wss://...' as the base URL.","commonSituations":"Users omitting the https:// prefix; API examples copied with a scheme the backend does not speak; attempts to point the provider at local files.","solutions":["Prefix the URL with http:// or https:// (https for real providers).","Strip any protocol prefix from user input and re-add https:// programmatically.","Reject non-http schemes in the client form before submission."],"exampleFix":"# before\nvalidate_provider_base_url(\"api.openai.com/v1\")\n# after\nvalidate_provider_base_url(\"https://api.openai.com/v1\")","handlingStrategy":"validation","validationCode":"from urllib.parse import urlsplit\nif urlsplit(raw).scheme.lower() not in (\"http\", \"https\"):\n    raw = \"https://\" + raw  # or reject","typeGuard":"def has_http_scheme(raw: str) -> bool:\n    from urllib.parse import urlsplit\n    return urlsplit(raw).scheme.lower() in (\"http\", \"https\")","tryCatchPattern":null,"preventionTips":["Auto-prefix https:// when users omit the scheme.","Reject ftp/file/ws schemes in the form layer."],"tags":["validation","url-scheme","provider-config"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}