{"id":"3463071ff348f5e6","repo":"psf/requests","slug":"header-part-header-part-r-from-header-must-b","errorCode":null,"errorMessage":"Header part ({header_part!r}) from {header} must be of type str or bytes, not {type(header_part)}","messagePattern":"Header part \\((.+?)\\) from (.+?) must be of type str or bytes, not (.+?)","errorType":"validation","errorClass":"InvalidHeader","httpStatus":null,"severity":"error","filePath":"src/requests/utils.py","lineNumber":1109,"sourceCode":"    :param header: tuple, in the format (name, value).\n    \"\"\"\n    name, value = header\n    _validate_header_part(header, name, 0)\n    _validate_header_part(header, value, 1)\n\n\ndef _validate_header_part(\n    header: tuple[str | bytes, str | bytes],\n    header_part: str | bytes,\n    header_validator_index: int,\n) -> None:\n    if isinstance(header_part, str):\n        validator = _HEADER_VALIDATORS_STR[header_validator_index]\n    elif isinstance(header_part, bytes):\n        # runtime guard for non-str/bytes input\n        validator = _HEADER_VALIDATORS_BYTE[header_validator_index]\n    else:\n        raise InvalidHeader(\n            f\"Header part ({header_part!r}) from {header} \"\n            f\"must be of type str or bytes, not {type(header_part)}\"\n        )\n\n    if not validator.match(header_part):  # type: ignore[arg-type]\n        header_kind = \"name\" if header_validator_index == 0 else \"value\"\n        raise InvalidHeader(\n            f\"Invalid leading whitespace, reserved character(s), or return \"\n            f\"character(s) in header {header_kind}: {header_part!r}\"\n        )\n\n\ndef urldefragauth(url: str) -> str:\n    \"\"\"\n    Given a url remove the fragment and the authentication part.\n\n    :rtype: str\n    \"\"\"","sourceCodeStart":1091,"sourceCodeEnd":1127,"githubUrl":"https://github.com/psf/requests/blob/414f0513c33883adf6f2b46901d4f0b38a455851/src/requests/utils.py#L1091-L1127","documentation":"Raised as `requests.exceptions.InvalidHeader` from `_validate_header_part()` in `src/requests/utils.py:1109`. Before sending, requests validates every header name and value via `check_header_validity()`; each part must be `str` or `bytes` so it can be matched against the appropriate regex validator. Any other type (int, None, list, dict, etc.) cannot be validated or serialized onto the wire, so requests fails fast instead of sending a malformed header.","triggerScenarios":"Passing a non-string header value or name in the `headers=` dict of any request call, e.g. `requests.get(url, headers={'X-Retry-Count': 3})` or `{'Authorization': None}` (when set per-request rather than deleted), or setting `session.headers['X-Id'] = uuid.uuid4()` without str().","commonSituations":"Numeric values (ports, counts, timestamps) placed directly into headers without str(); values loaded from JSON/YAML config that parse as int/bool/None; passing a `uuid.UUID`, `datetime`, or f-string forgotten object; accidentally assigning a list of values instead of a comma-joined string.","solutions":["Convert the offending header value to a string: `headers={'X-Retry-Count': str(3)}` — the exception message shows exactly which part and its type.","If loading headers from config/JSON, coerce all values with `{k: str(v) for k, v in headers.items() if v is not None}`.","To remove a default header on a Session, delete it (`del session.headers['Accept-Encoding']`) rather than setting it to None per-request only works at the Session level — per-request None is invalid.","For multiple values, join them yourself: `', '.join(values)`."],"exampleFix":"# before\nrequests.get(url, headers={'X-Request-Id': uuid.uuid4(), 'X-Retries': 3})\n# after\nrequests.get(url, headers={'X-Request-Id': str(uuid.uuid4()), 'X-Retries': '3'})","handlingStrategy":"type-guard","validationCode":"def headers_are_valid_types(headers):\n    return all(isinstance(k, (str, bytes)) and isinstance(v, (str, bytes)) for k, v in headers.items())","typeGuard":"def is_header_part(value):\n    \"\"\"Requests requires header names/values to be str or bytes.\"\"\"\n    return isinstance(value, (str, bytes))","tryCatchPattern":"try:\n    resp = requests.get(url, headers=headers)\nexcept requests.exceptions.InvalidHeader as e:\n    log.error('Header has wrong type: %s', e)","preventionTips":["Convert non-string header values explicitly (str(value)) before building the headers dict — ints, None, and objects are rejected","Type-check header dicts at your API boundary, especially when values come from config files or JSON","Don't put None in a header value to 'unset' a default unless you intend requests' skip-header behavior; audit those cases"],"tags":["headers","type-error","validation","python","requests"],"analyzedSha":"414f0513c33883adf6f2b46901d4f0b38a455851","analyzedAt":"2026-07-31T19:24:57.696Z","schemaVersion":2}