{"record":{"id":"3740b09fe47bea0e","repo":"BerriAI/litellm","slug":"api-base-is-required-for-azure-websocket","errorCode":null,"errorMessage":"api_base is required for Azure WebSocket","messagePattern":"api_base is required for Azure WebSocket","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/azure/responses/transformation.py","lineNumber":189,"sourceCode":"            route=\"/openai/responses\",\n            default_api_version=AZURE_DEFAULT_RESPONSES_API_VERSION,\n        )\n\n    def supports_native_websocket(self) -> bool:\n        return True\n\n    def get_websocket_url(\n        self,\n        api_base: str | None,\n        litellm_params: dict,\n    ) -> str:\n        \"\"\"\n        Azure Responses WebSocket endpoint is at /openai/v1/responses with no\n        api-version query param. Auth is via Authorization header, model is sent\n        in the response.create body — not the URL.\n        \"\"\"\n        if api_base is None:\n            raise ValueError(\"api_base is required for Azure WebSocket\")\n\n        parsed_url: Final = httpx.URL(api_base)\n        path = parsed_url.path.rstrip(\"/\")\n        # Strip existing /openai/responses path if the api_base already contains it\n        for suffix in (\"/openai/v1/responses\", \"/openai/responses\"):\n            if path.endswith(suffix):\n                path = path[: -len(suffix)]\n                break\n        scheme: Final = \"wss\" if parsed_url.scheme == \"https\" else \"ws\"\n        return str(parsed_url.copy_with(scheme=scheme, path=f\"{path}/openai/v1/responses\", query=None))\n\n    def model_in_websocket_url(self) -> bool:\n        # Azure sends the model in the response.create body, not the URL\n        return False\n\n    #########################################################\n    ########## DELETE RESPONSE API TRANSFORMATION ##############\n    #########################################################","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/azure/responses/transformation.py#L171-L207","documentation":"Azure Responses over WebSocket targets <api_base>/openai/v1/responses (scheme rewritten to wss/ws, model sent in the response.create body). This method requires api_base to build that URL; if api_base is None it raises ValueError before any parsing or connection. Existing /openai/responses or /openai/v1/responses suffixes in the base are stripped, so the root resource URL is the expected input.","triggerScenarios":"Calling get_websocket_url(None, litellm_params) — i.e. invoking Azure Responses streaming-over-WebSocket without an api_base in the call, litellm_params, or ambient config.","commonSituations":"Adopting the Responses API with configs written for chat completions that omit api_base; per-model config where api_base was placed on a different model entry; environment migrations that drop AZURE_API_BASE.","solutions":["Pass api_base='https://<resource>.openai.azure.com' to the responses WebSocket call.","Add api_base to the Azure model's litellm_params so it reaches get_websocket_url.","Or set the AZURE_API_BASE environment variable if your integration resolves the base from env.","Do not pre-append /openai/v1/responses to the base — the handler constructs the path itself."],"exampleFix":"# before\nurl = transformation.get_websocket_url(None, litellm_params={})  # raises\n\n# after\nurl = transformation.get_websocket_url('https://myresource.openai.azure.com', litellm_params={})\n# -> 'wss://myresource.openai.azure.com/openai/v1/responses'","handlingStrategy":"validation","validationCode":"def validate_responses_ws_base(api_base: str | None, litellm_params: dict) -> str:\n    base = api_base or litellm_params.get('api_base')\n    if not base:\n        raise ValueError('Azure Responses WebSocket requires api_base (resource root URL)')\n    return base","typeGuard":null,"tryCatchPattern":"try:\n    url = transformation.get_websocket_url(api_base, litellm_params)\nexcept ValueError as e:\n    if 'api_base is required' in str(e):\n        raise ValueError('set api_base to https://<resource>.openai.azure.com for responses WS') from e\n    raise","preventionTips":["Pass the resource root URL; the handler appends /openai/v1/responses itself.","Mirror chat-completion model configs (which already carry api_base) when enabling Responses."],"tags":["azure","openai","responses-api","websocket","api-base","configuration"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}