SeleniumHQ/selenium · warning · ValueError
Extra header '{name}' not found
Error message
Extra header '{name}' not found What it means
Raised as a ValueError by ExtraHeadersMixin.remove_extra_header() when the given header name (lowercased) is not present in the extra_headers dictionary. The method calls extra_headers.pop(name.lower(), None); if the default None is returned (meaning the key was absent), it raises. Extra headers are tracked case-insensitively by lowercasing on both add and remove.
Source
Thrown at py/private/_network_handlers.py:806
self._extra_headers_intercept: str | None = None
def _wrap(self, params):
return Request(self._network._conn, params, deferred=True)
def set_extra_header(self, name: str, value: str) -> None:
"""Record a header to merge into every subsequent request."""
self.extra_headers[name.lower()] = value
if self._extra_headers_intercept is None:
result = self._network._add_intercept(phases=[self._phase])
self._extra_headers_intercept = result.get("intercept") if result else None
if self._subscription_callback_id is None:
self._subscription_callback_id = self._network.add_event_handler(self._event_name, self._on_event)
logger.debug("Added extra header %s", name.lower())
def remove_extra_header(self, name: str) -> None:
"""Stop merging a header by (case-insensitive) name."""
if self.extra_headers.pop(name.lower(), None) is None:
raise ValueError(f"Extra header '{name}' not found")
if not self.extra_headers:
self._drop_extra_headers_intercept()
logger.debug("Removed extra header %s", name.lower())
def clear_extra_headers(self) -> None:
"""Stop merging all extra headers."""
self.extra_headers.clear()
self._drop_extra_headers_intercept()
def _drop_extra_headers_intercept(self) -> None:
if self._extra_headers_intercept:
self._network._remove_intercept(self._extra_headers_intercept)
self._extra_headers_intercept = None
if not self._keep_subscription() and self._subscription_callback_id is not None:
self._network.remove_event_handler(self._event_name, self._subscription_callback_id)
self._subscription_callback_id = None
def intercept_ids(self) -> set:View on GitHub (pinned to aa36b38e69)
Solutions
- Track which headers you have added and only remove ones that exist, or guard with a membership check.
- Use clear_extra_headers() to remove all headers at once instead of removing individually.
- Set a variable to track the added header names and null them out after removal to prevent double-removal.
Example fix
# before
extra_headers.set_extra_header('X-Custom', 'value')
extra_headers.remove_extra_header('X-Custom')
extra_headers.remove_extra_header('X-Custom') # ValueError
# after
added_headers = set()
extra_headers.set_extra_header('X-Custom', 'value')
added_headers.add('x-custom')
if 'x-custom' in added_headers:
extra_headers.remove_extra_header('X-Custom')
added_headers.discard('x-custom') Defensive patterns
Strategy: validation
Validate before calling
# Track added headers and check before removing
added = set()
extra_headers.set_extra_header('X-Custom', 'val')
added.add('x-custom')
if name.lower() in added:
extra_headers.remove_extra_header(name)
added.discard(name.lower()) Try / catch
try:
extra_headers.remove_extra_header(name)
except ValueError as e:
if 'not found' in str(e):
# header was never added or already removed
pass
else:
raise Prevention
- Track added header names in a set and discard after removal.
- Use clear_extra_headers() to remove all at once.
- Remember header names are matched case-insensitively (lowercased).
When it happens
Trigger: Calling remove_extra_header(name) where 'name.lower()' was never added via set_extra_header/add_extra_header, or was already removed. The pop returns None and the ValueError fires.
Common situations: Calling remove_extra_header before any header with that name was added; double-removal of the same header; case mismatch that was actually already handled by lowercasing but the header simply was not set; calling remove after clear_extra_headers emptied the dictionary.
Related errors
- {self._label.capitalize()} '{handler_id}' not found
- Port must be a number. Received:'${port}'
- Event '{event}' not found. Available events: {self._availabl
- Unsupported DOM mutation type(s) {sorted(unknown)}; expected
- mutation_types must name at least one mutation type
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/3a6b2af5264101ba.
Report an issue: GitHub.