{"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/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/client.py#L611-L647","documentation":"Raised in `_request` (client.py:623-632) on the *initial* request (`not history`) when the URL contains userinfo (`user:pass@host`) AND the caller also set an explicit `Authorization` header. aiohttp refuses to silently shadow a hand-set Authorization header with URL-embedded credentials — a deliberate fail-fast to prevent credential confusion. On redirects (`history` non-empty), URL credentials override silently, which is why the guard is gated on `not history`.","triggerScenarios":"`session.get('https://user:pass@host/path', headers={'Authorization': 'Bearer x'})`. Also via netrc auto-credentials combined with a URL that has its own userinfo, or via a redirect-captured Authorization header reaching a URL with embedded creds.","commonSituations":"Mixing bearer-token auth with a legacy URL that still has basic-auth creds baked in; copy-pasting a URL from a browser that exposed credentials; CI configs that put secrets in the URL and also pass a header.","solutions":["Remove credentials from the URL and keep only the Authorization header (`https://host/path` + `headers={'Authorization': ...}`).","Or remove the Authorization header and let URL-embedded basic auth populate it (`https://user:pass@host`).","Avoid putting credentials in URLs entirely — they leak into logs, proxies, and Referer."],"exampleFix":"// before\nawait session.get('https://u:p@host/api', headers={'Authorization': 'Bearer t'})\n// after\nawait session.get('https://host/api', headers={'Authorization': 'Bearer t'})","handlingStrategy":"validation","validationCode":"from yarl import URL\n\ndef strip_url_credentials(url, headers):\n    u = URL(url)\n    if u.user is not None and 'Authorization' in (headers or {}):\n        raise ValueError('Cannot combine AUTHORIZATION header with URL credentials')\n    return str(u.with_user(None).with_password(None)) if u.user else url","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never embed credentials in URLs — they leak into logs and proxies.","Pick one auth mechanism: either an Authorization header or URL userinfo, not both.","Sanitize URLs from config/untrusted sources with yarl's `.with_user(None)`."],"tags":["client","authentication","security","url"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}