{"id":"d97bc89b2dd6e20e","repo":"psf/requests","slug":"cannot-encode-objects-that-are-not-2-tuples","errorCode":null,"errorMessage":"cannot encode objects that are not 2-tuples","messagePattern":"cannot encode objects that are not 2-tuples","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/requests/utils.py","lineNumber":365,"sourceCode":"\n    ::\n\n        >>> from_key_val_list([('key', 'val')])\n        OrderedDict([('key', 'val')])\n        >>> from_key_val_list('string')\n        Traceback (most recent call last):\n        ...\n        ValueError: cannot encode objects that are not 2-tuples\n        >>> from_key_val_list({'key': 'val'})\n        OrderedDict([('key', 'val')])\n\n    :rtype: OrderedDict\n    \"\"\"\n    if value is None:\n        return None\n\n    if isinstance(value, (str, bytes, bool, int)):\n        raise ValueError(\"cannot encode objects that are not 2-tuples\")\n\n    return OrderedDict(value)\n\n\n@overload\ndef to_key_val_list(value: None) -> None: ...\n@overload\ndef to_key_val_list(\n    value: _t.SupportsItems[_KT, _VT] | Iterable[tuple[_KT, _VT]],\n) -> list[tuple[_KT, _VT]]: ...\ndef to_key_val_list(\n    value: _t.SupportsItems[_KT, _VT] | Iterable[tuple[_KT, _VT]] | None,\n) -> list[tuple[_KT, _VT]] | None:\n    \"\"\"Take an object and test to see if it can be represented as a\n    dictionary. If it can be, return a list of tuples, e.g.,\n\n    ::\n","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/psf/requests/blob/414f0513c33883adf6f2b46901d4f0b38a455851/src/requests/utils.py#L347-L383","documentation":"utils.from_key_val_list converts a user-supplied value into an OrderedDict and explicitly rejects str, bytes, bool, and int inputs with this ValueError, because iterating those would not yield the (key, value) 2-tuples an OrderedDict requires (a string would explode into characters). It's a fail-fast guard on parameters that requests accepts as either a mapping or an iterable of pairs.","triggerScenarios":"Passing a scalar or string where a dict/list-of-tuples is expected and requests routes it through from_key_val_list at src/requests/utils.py:364-365 — e.g. malformed header/param structures fed into internal conversion. Directly: from_key_val_list('key=val') or from_key_val_list(True).","commonSituations":"Passing a pre-encoded query string or 'k=v' string where a dict was expected; JSON config deserializing a field as a plain string instead of an object; passing a single ('k','v') tuple flattened incorrectly, or booleans/ints from templated config landing in dict-shaped parameters.","solutions":["Pass a mapping or an iterable of 2-tuples: {'key': 'val'} or [('key', 'val')] instead of a string/scalar","If you have a query string, parse it first with urllib.parse.parse_qsl before handing it to requests","Validate config-loaded values are dict-shaped before passing them into requests parameters"],"exampleFix":"# before\nfrom_key_val_list('key=val')  # ValueError\n\n# after\nfrom urllib.parse import parse_qsl\nfrom_key_val_list(parse_qsl('key=val'))  # OrderedDict([('key', 'val')])","handlingStrategy":"type-guard","validationCode":"def validate_params(data):\n    if hasattr(data, \"items\"):\n        return\n    for item in data:\n        if not (hasattr(item, \"__len__\") and len(item) == 2):\n            raise ValueError(f\"Each element must be a 2-tuple (key, value), got {item!r}\")","typeGuard":"def is_two_tuple_sequence(data):\n    return hasattr(data, \"items\") or all(\n        isinstance(i, (tuple, list)) and len(i) == 2 for i in data\n    )","tryCatchPattern":"try:\n    resp = session.get(url, params=param_pairs)\nexcept ValueError as e:\n    if \"2-tuples\" in str(e):\n        raise ConfigError(f\"params must be a dict or list of (key, value) pairs: {param_pairs!r}\") from e\n    raise","preventionTips":["Pass params/data as a dict, or as a list of exactly (key, value) pairs — never a flat list of strings","Watch for accidental 3-tuples or bare strings when building pair lists programmatically","Unit-test the pair-building code with representative inputs before hitting the network"],"tags":["python","validation","data-structures","api-usage"],"analyzedSha":"414f0513c33883adf6f2b46901d4f0b38a455851","analyzedAt":"2026-07-31T19:24:57.696Z","schemaVersion":2}