aio-libs/aiohttp · error · ValueError
A ":" is not allowed in login (RFC 7617#section-2)
Error message
A ":" is not allowed in login (RFC 7617#section-2)
What it means
Raised by encode_basic_auth when the login contains a colon. RFC 7617 section 2 defines the user-id as everything before the first colon of the 'user:pass' credential string, so an embedded colon in the login makes the encoding ambiguous and aiohttp rejects it with ValueError before base64-encoding.
Source
Thrown at aiohttp/helpers.py:167
"{",
"}",
" ",
chr(9),
}
TOKEN = CHAR ^ CTL ^ SEPARATORS
json_re = re.compile(r"^(?:application/|[\w.-]+/[\w.+-]+?\+)json$", re.IGNORECASE)
def encode_basic_auth(login: str, password: str = "", encoding: str = "utf-8") -> str:
"""Encode HTTP Basic Authentication credentials as an Authorization header value.
Returns a string of the form ``"Basic <base64>"`` suitable for use as the
value of the ``Authorization`` (or ``Proxy-Authorization``) header.
"""
if ":" in login:
raise ValueError('A ":" is not allowed in login (RFC 7617#section-2)')
creds = f"{login}:{password}".encode(encoding)
return "Basic " + base64.b64encode(creds).decode(encoding)
def strip_auth_from_url(url: URL) -> tuple[URL, str | None]:
"""Strip user/password from a URL and return the Authorization header value.
Returns a tuple of ``(url_without_credentials, authorization_header_value)``.
The header value is ``None`` if no credentials were present.
"""
# Check raw_user and raw_password first as yarl is likely
# to already have these values parsed from the netloc in the cache.
if url.raw_user is None and url.raw_password is None:
return url, None
return url.with_user(None), encode_basic_auth(url.user or "", url.password or "")
def netrc_from_env() -> netrc.netrc | None:View on GitHub (pinned to c0ef574e29)
Solutions
- Remove the colon from the login or URL-encode the username portion.
- Split 'user:pass' strings yourself instead of passing the whole thing as login.
- Use BasicAuth(login, password) with separate arguments, never embedding ':' in login.
Example fix
// before
auth = aiohttp.BasicAuth('john:doe', 'secret')
// after
auth = aiohttp.BasicAuth('john', 'secret') Defensive patterns
Strategy: validation
Validate before calling
def split_basic_auth(s):
login, _, password = s.partition(':')
if ':' in login:
raise ValueError('colon in login')
return login, password Type guard
def is_valid_basic_login(login) -> bool:
return isinstance(login, str) and ':' not in login Prevention
- Always pass BasicAuth(login, password) with separate args.
- Reject or sanitize colons in usernames at the source.
- Never paste 'user:pass' as the login field.
When it happens
Trigger: Calling aiohttp.BasicAuth('user:name', 'pass') or encode_basic_auth('a:b'). Also indirectly via strip_auth_from_url when a URL embeds a user with a colon (URLs forbid it but crafted input can).
Common situations: Email-style logins used as HTTP usernames; concatenating domain\\user incorrectly; config sourced from upstream that includes colons.
Related errors
- Compress wbits must between 9 and 15, zlib does not support
- base_url must have a trailing '/'
- data and json parameters can not be used at the same time
- None is not allowed as login value
- None is not allowed as password value
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/beb984c6995c79a0.json.
Report an issue: GitHub.