{"record":{"id":"6c50748fda607d71","repo":"FoundationAgents/MetaGPT","slug":"openai-proxy-must-be-specified-as-either-a-strin","errorCode":null,"errorMessage":"'openai.proxy' must be specified as either a string URL or a dict with string URL under the https and/or http keys.","messagePattern":"'openai\\.proxy' must be specified as either a string URL or a dict with string URL under the https and/or http keys\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"metagpt/provider/general_api_base.py","lineNumber":180,"sourceCode":"def _build_api_url(url, query):\n    scheme, netloc, path, base_query, fragment = urlsplit(url)\n\n    if base_query:\n        query = \"%s&%s\" % (base_query, query)\n\n    return urlunsplit((scheme, netloc, path, query, fragment))\n\n\ndef _requests_proxies_arg(proxy) -> Optional[Dict[str, str]]:\n    \"\"\"Returns a value suitable for the 'proxies' argument to 'requests.request.\"\"\"\n    if proxy is None:\n        return None\n    elif isinstance(proxy, str):\n        return {\"http\": proxy, \"https\": proxy}\n    elif isinstance(proxy, dict):\n        return proxy.copy()\n    else:\n        raise ValueError(\n            \"'openai.proxy' must be specified as either a string URL or a dict with string URL under the https and/or http keys.\"\n        )\n\n\ndef _aiohttp_proxies_arg(proxy) -> Optional[str]:\n    \"\"\"Returns a value suitable for the 'proxies' argument to 'aiohttp.ClientSession.request.\"\"\"\n    if proxy is None:\n        return None\n    elif isinstance(proxy, str):\n        return proxy\n    elif isinstance(proxy, dict):\n        return proxy[\"https\"] if \"https\" in proxy else proxy[\"http\"]\n    else:\n        raise ValueError(\n            \"'openai.proxy' must be specified as either a string URL or a dict with string URL under the https and/or http keys.\"\n        )\n\n","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/provider/general_api_base.py#L162-L198","documentation":"This ValueError is raised by MetaGPT's vendored OpenAI-compatible HTTP layer (_requests_proxies_arg) when the proxy setting passed to a provider resolves to neither None, a string, nor a dict. The helper builds the 'proxies' argument for requests.request, so any other Python type (int, list, tuple, bool) is rejected immediately. It surfaces as an 'openai.proxy' error because the value normally originates from the proxy field of the LLM provider config.","triggerScenarios":"Calling any provider built on metagpt/provider/general_api_base.py (OpenAI, Azure, self-hosted endpoints) with a proxy config value that is truthy but not a string or dict, e.g. proxy: 1, proxy: [\"http://host:port\"], or proxy: true in yaml; the sync requests path then formats proxies and hits the else-branch.","commonSituations":"YAML config typos (unquoted port numbers, a list instead of a single URL), environment variables parsed into non-string types, programmatic Config construction that passes os.environ values or integers, or copying a curl-style proxy list into config2.yaml.","solutions":["Set the proxy as a single string URL, e.g. proxy: \"http://127.0.0.1:7890\" in config2.yaml.","Or set it as a dict with string URLs under http/https keys, e.g. proxy: {http: \"http://127.0.0.1:7890\", https: \"http://127.0.0.1:7890\"}.","If no proxy is intended, set proxy to null/omit it so the helper returns None instead of raising.","Check code that builds the provider Config programmatically and cast the value with str() before passing it."],"exampleFix":"# before (config2.yaml)\nllm:\n  proxy: 7890          # int -> ValueError\n\n# after\nllm:\n  proxy: \"http://127.0.0.1:7890\"","handlingStrategy":"type-guard","validationCode":"def is_valid_proxy(p) -> bool:\n    return p is None or isinstance(p, str) or (\n        isinstance(p, dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in p.items())\n    )\n\nassert is_valid_proxy(config.llm.proxy), \"proxy must be str URL or dict of str URLs\"","typeGuard":"from typing import Union, Optional, Dict\n\ndef is_proxy_config(p) -> TypeGuard[Union[str, Dict[str, str], None]]:\n    if p is None or isinstance(p, str):\n        return True\n    return isinstance(p, dict) and all(isinstance(v, str) for v in p.values())","tryCatchPattern":"try:\n    provider = OpenAIGPTAPI(config)\nexcept ValueError as e:\n    if \"openai.proxy\" in str(e):\n        raise SystemExit(f\"Fix proxy config: {e}\") from e\n    raise","preventionTips":["Quote proxy URLs in YAML so they load as strings","Centralize proxy config validation at app startup","Never pass raw CLI args or env values as proxy without str() conversion"],"tags":["configuration","proxy","openai","validation"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}