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

  1. Track which headers you have added and only remove ones that exist, or guard with a membership check.
  2. Use clear_extra_headers() to remove all headers at once instead of removing individually.
  3. 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

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


AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14). Data as JSON: /api/errors/3a6b2af5264101ba. Report an issue: GitHub.