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
encode_basic_auth raises ValueError when the login (username) string contains a colon character. Per RFC 7617 Section 2, the colon is the delimiter between userid and password in the Basic credentials, so it cannot appear in the userid itself. This is a hard validation, not a warning.
Solutions
- Remove or replace the colon in the login: use a sanitized username
- URL-encode the colon in the userinfo: replace ':' with '%3A' in the URL (yarl may handle this)
- Pass credentials via the auth parameter instead of embedding in the URL: ClientSession(auth=BasicAuth('user', 'pass'))
Example fix
# before
await session.get('http://user:name@host/api')
# after
from aiohttp import BasicAuth
await session.get('http://host/api', auth=BasicAuth('user', 'password')) Defensive patterns
Strategy: validation
Validate before calling
def safe_basic_auth(login, password='', encoding='utf-8'):
if ':' in login:
raise ValueError(f'Login contains illegal colon: {login!r}')
from aiohttp.helpers import encode_basic_auth
return encode_basic_auth(login, password, encoding) Type guard
def is_valid_basic_auth_login(login: str) -> bool:
return isinstance(login, str) and ':' not in login Try / catch
try:
from aiohttp.helpers import encode_basic_auth
header = encode_basic_auth(login, password)
except ValueError as e:
if 'not allowed in login' in str(e):
login = login.replace(':', '')
header = encode_basic_auth(login, password)
raise Prevention
- Validate usernames for colon characters before constructing auth
- Prefer the auth= parameter over embedding credentials in URLs
- Sanitize credentials from external sources before passing to BasicAuth
When it happens
Trigger: Calling aiohttp.helpers.encode_basic_auth(login='user:name', password='secret'), or providing a URL with userinfo like http://user:name@host/. Also triggered indirectly when aiohttp encodes credentials from a URL or from BasicAuth(login, password) where login contains ':'.
Common situations: Email addresses used as usernames ('user@example.com' is fine, but 'user:name' is not); Active Directory UPN with colons; copy-pasted credentials from a config that uses colon-delimited format; URLs with encoded or raw colons in the userinfo component.
Related errors
- A ":" is not allowed in username (RFC 1945#section-11.1)
- None is not allowed as login value
- None is not allowed as password value
- 1007
- bad content disposition parameter
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/beb984c6995c79a0.
Report an issue: GitHub.
Appendix: 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 d041d4d0fd)