aio-libs/aiohttp · error · ValueError
None is not allowed as password value
Error message
None is not allowed as password value
What it means
Raised by DigestAuthMiddleware.__init__ when password is None. Mirrors the login check: the password is encoded to bytes immediately, so a None value would AttributeError later; the constructor rejects it up front.
Solutions
- Provide a concrete password string (empty string '' is accepted if you genuinely mean empty).
- Load via a secret manager that errors on missing keys instead of returning None.
- Validate both credentials together at the config boundary.
Example fix
// before
mw = DigestAuthMiddleware(login='user', password=os.getenv('API_PASS'))
// after
import os
mw = DigestAuthMiddleware(login='user', password=os.environ['API_PASS']) Defensive patterns
Strategy: validation
Validate before calling
def require_password(password):
if password is None:
raise ValueError('password is required')
return password
DigestAuthMiddleware(login=login, password=require_password(password)) Type guard
def is_nonnull_password(v) -> bool:
return v is not None and isinstance(v, str) Try / catch
try:
mw = DigestAuthMiddleware(login=login, password=password)
except ValueError as e:
if 'password' in str(e):
raise SystemExit('API password not configured')
raise Prevention
- Read secrets via a manager that raises on missing values.
- Validate both credentials together at config load.
- Never forward optional config values directly into auth constructors.
When it happens
Trigger: Constructing DigestAuthMiddleware(login='user', password=None). Most often the result of an env var or secret lookup returning None and being forwarded.
Common situations: Password secret not loaded (key name typo, vault path wrong). Default of None on a CLI flag. Asymmetric config where username is set but password is not.
Related errors
- None is not allowed as login value
- A ":" is not allowed in username (RFC 1945#section-11.1)
- A ":" is not allowed in login (RFC 7617#section-2)
- base_url must have a trailing '/'
- compress must be one of True, False, 'deflate', or 'gzip'
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/6f3d95759efb03dd.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/client_middleware_digest_auth.py:206
- RFC 1945: Section 11.1 (username restrictions)
Implementation notes:
The core digest calculation is inspired by the implementation in
https://github.com/requests/requests/blob/v2.18.4/requests/auth.py
with added support for modern digest auth features and error handling.
"""
def __init__(
self,
login: str,
password: str,
preemptive: bool = True,
) -> None:
if login is None:
raise ValueError("None is not allowed as login value")
if password is None:
raise ValueError("None is not allowed as password value")
if ":" in login:
raise ValueError('A ":" is not allowed in username (RFC 1945#section-11.1)')
self._login_str: Final[str] = login
self._login_bytes: Final[bytes] = login.encode("utf-8")
self._password_bytes: Final[bytes] = password.encode("utf-8")
self._last_nonce_bytes = b""
self._nonce_count = 0
self._challenge: DigestAuthChallenge = {}
self._preemptive: bool = preemptive
# Set of URLs defining the protection space
self._protection_space: list[str] = []
# Origin the credentials are scoped to; set on the first request.
self._origin: URL | None = None
async def _encode(self, method: str, url: URL, body: Payload | Literal[b""]) -> str:View on GitHub (pinned to d041d4d0fd)