psf/requests · warning · NotImplementedError
Cookie headers should be added with…
Error message
Cookie headers should be added with add_unredirected_header()
What it means
Raised by MockRequest.add_header (the shim used by requests.cookies to bridge to urllib3/http.cookiejar). The cookiejar machinery calls add_header for certain operations, but requests manages cookie headers exclusively via add_unredirected_header, so this method intentionally refuses. It exists purely to redirect maintainers to the correct API.
Solutions
- Call add_unredirected_header(name, value) instead of add_header(key, val) when adding cookie headers to a requests MockRequest.
- If you are managing cookies at the user level, set them via the session's cookies jar (session.cookies.set(name, value)) or pass the cookies= dict to request(), which routes through the correct API.
- If the call comes from inside cookiejar internals, report it upstream; the message itself invites you to add the method back if you find a legitimate use.
Example fix
// before
mock_request.add_header('Cookie', 'sid=abc')
// after
mock_request.add_unredirected_header('Cookie', 'sid=abc') Defensive patterns
Strategy: validation
Validate before calling
# This is internal API; user-level code should not call add_header on the MockRequest.
# Validate at the cookie-management level instead:
from http.cookiejar import CookieJar
def safe_set_cookie(jar, name, value, domain=None, path='/'):
assert isinstance(jar, CookieJar)
jar.set_cookie(create_cookie(name=name, value=value, domain=domain, path=path)) Type guard
# Low-level guard if you must handle a MockRequest-like object:
from typing import Protocol
class HasUnredirectedHeader(Protocol):
def add_unredirected_header(self, name: str, value: str) -> None: ...
def is_mock_request(obj) -> bool:
return hasattr(obj, 'add_unredirected_header') and hasattr(obj, 'get_new_headers') Try / catch
# Not typically caught; prefer to avoid calling add_header at all.
# If integrating with code that may call add_header, wrap it:
try:
obj.add_header(k, v)
except NotImplementedError:
obj.add_unredirected_header(k, v) Prevention
- Never call add_header on requests' internal MockRequest; use add_unredirected_header.
- Manage cookies through session.cookies / the cookies= argument, not low-level header injection.
- If you maintain a cookie policy subclass, override add_unredirected_header rather than add_header.
When it happens
Trigger: Calling .add_header(key, val) on the MockRequest object that requests wraps around each PreparedRequest when feeding cookies through a CookieJar; internal cookiejar flows that route through add_header when the cookie policy triggers a header-set path.
Common situations: Monkey-patching or instrumenting cookie handling and accidentally hitting add_header; downstream libraries that operate on http.cookiejar.CookieJar abstractions and assume add_header works; a fork or fork-equivalent that wires its own cookie policy.
Related errors
- name= , domain= , path=
- There are multiple cookies with name
- Auth hooks must be callable.
- Streamed bodies and files are mutually exclusive.
- You can only merge into CookieJar
AI-assisted analysis of psf/requests@8068356288 (2026-08-11).
Data as JSON: /api/errors/3154592a1005157a.
Report an issue: GitHub.
Appendix: source
Thrown at src/requests/cookies.py:91
parsed.path,
parsed.params,
parsed.query,
parsed.fragment,
]
)
def is_unverifiable(self) -> bool:
return True
def has_header(self, name: str) -> bool:
return name in self._r.headers or name in self._new_headers
def get_header(self, name: str, default: str | None = None) -> str | None:
return self._r.headers.get(name, self._new_headers.get(name, default)) # type: ignore[return-value]
def add_header(self, key: str, val: str) -> None:
"""cookiejar has no legitimate use for this method; add it back if you find one."""
raise NotImplementedError(
"Cookie headers should be added with add_unredirected_header()"
)
def add_unredirected_header(self, name: str, value: str) -> None:
self._new_headers[name] = value
def get_new_headers(self) -> dict[str, str]:
return self._new_headers
@property
def unverifiable(self) -> bool:
return self.is_unverifiable()
@property
def origin_req_host(self) -> str:
return self.get_origin_req_host()
@propertyView on GitHub (pinned to 8068356288)