{"record":{"id":"d6f1c55ee555b43d","repo":"aio-libs/aiohttp","slug":"cannot-combine-authorization-header-with-credentia","errorCode":null,"errorMessage":"Cannot combine AUTHORIZATION header with credentials encoded in URL","messagePattern":"Cannot combine AUTHORIZATION header with credentials encoded in URL","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":629,"sourceCode":"                while True:\n                    url, auth_from_url = strip_auth_from_url(url)\n                    if not url.raw_host:\n                        # NOTE: Bail early, otherwise, causes `InvalidURL` through\n                        # NOTE: `self._request_class()` below.\n                        err_exc_cls = (\n                            InvalidUrlRedirectClientError\n                            if redirects\n                            else InvalidUrlClientError\n                        )\n                        raise err_exc_cls(url)\n\n                    if auth_from_url is not None:\n                        # URL-embedded credentials override any Authorization\n                        # header already present (e.g. carried from a previous\n                        # redirect). On the initial request, refuse to silently\n                        # shadow an explicit Authorization header.\n                        if not history and hdrs.AUTHORIZATION in headers:\n                            raise ValueError(\n                                \"Cannot combine AUTHORIZATION header with \"\n                                \"credentials encoded in URL\"\n                            )\n                        headers[hdrs.AUTHORIZATION] = auth_from_url\n                    elif (\n                        self._trust_env\n                        and url.host is not None\n                        and hdrs.AUTHORIZATION not in headers\n                    ):\n                        # Fall back to ~/.netrc credentials when trust_env is set.\n                        netrc_auth = await self._loop.run_in_executor(\n                            None, self._get_netrc_auth, url.host\n                        )\n                        if netrc_auth is not None:\n                            headers[hdrs.AUTHORIZATION] = netrc_auth\n\n                    all_cookies = self._cookie_jar.filter_cookies(url)\n","sourceCodeStart":611,"sourceCodeEnd":647,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/client.py#L611-L647","documentation":"Raised inside the request loop on the initial request (history is empty) when the URL contains userinfo (user:pass@host) AND an explicit Authorization header is present. aiohttp refuses to silently let URL credentials shadow a header the caller set, since that is a classic source of auth-bypass and credential-leak bugs.","triggerScenarios":"Calling session.get('https://user:pass@host/path', headers={'Authorization': 'Bearer x'}). Also when default headers on the session include Authorization and the URL has embedded credentials.","commonSituations":"Copy-pasting a URL with credentials from a deploy dashboard while also adding a token header. Session-level default Authorization header combined with a per-request URL that carries basic auth. Migrating from a lib that silently preferred one source.","solutions":["Remove credentials from the URL and keep only the Authorization header.","Or remove the Authorization header and let the URL's userinfo drive Basic auth.","If using a session-level Authorization header, strip userinfo from request URLs at build time."],"exampleFix":"// before\nawait session.get('https://user:pass@host/path', headers={'Authorization': 'Bearer x'})\n// after\nawait session.get('https://host/path', headers={'Authorization': 'Bearer x'})","handlingStrategy":"validation","validationCode":"from aiohttp import URL\nfrom multidict import CIMultiDict\n\ndef strip_url_userinfo_if_auth_header(url, headers):\n    if any(k.lower() == 'authorization' for k in headers):\n        u = URL(url)\n        if u.user is not None:\n            url = u.with_user(None).with_password(None)\n    return url","typeGuard":"from aiohttp import URL\n\ndef url_has_userinfo(u) -> bool:\n    u = URL(u)\n    return u.user is not None","tryCatchPattern":"try:\n    resp = await session.get(url, headers=headers)\nexcept ValueError as e:\n    if 'AUTHORIZATION' in str(e):\n        from aiohttp import URL\n        u = URL(url)\n        resp = await session.get(str(u.with_user(None).with_password(None)), headers=headers)\n    else:\n        raise","preventionTips":["Never embed credentials in URLs; use BasicAuth or explicit headers.","Build URLs from typed components instead of concatenating strings.","Strip userinfo at the URL construction boundary if Authorization headers are used."],"tags":["authentication","security","http-request","headers"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}