psf/requests · error · ValueError
cannot encode objects that are not 2-tuples
Error message
cannot encode objects that are not 2-tuples
What it means
Raised by from_key_val_list() when the input is a scalar type (str, bytes, bool, or int) that cannot be interpreted as an iterable of key-value pairs. This utility builds an OrderedDict from mappings or 2-tuple iterables. Scalar types are explicitly rejected because they would produce a confusing error inside OrderedDict().
Solutions
- Pass a dict or list of tuples instead of a scalar: from_key_val_list({'key': 'val'}).
- If you have a single string value, wrap it in a structure: from_key_val_list([('key', 'value')]).
- Check the type before calling: if not isinstance(value, (str, bytes, bool, int)).
Example fix
# before
from requests.utils import from_key_val_list
result = from_key_val_list('my string') # ValueError
# after
result = from_key_val_list({'my': 'string'}) Defensive patterns
Strategy: type-guard
Validate before calling
if isinstance(value, (str, bytes, bool, int)):
raise ValueError(f'Expected dict or iterable of tuples, got {type(value)}')
result = from_key_val_list(value) Type guard
from collections.abc import Mapping, Iterable
def is_key_val_capable(v) -> bool:
return v is None or isinstance(v, (Mapping,)) or (
isinstance(v, Iterable) and not isinstance(v, (str, bytes))
) Prevention
- Always pass dict or list-of-tuples to functions expecting key-value data.
- Use type annotations and a type checker to catch scalar inputs at development time.
- Wrap config-derived values in dict structures before passing to requests utilities.
When it happens
Trigger: Calling from_key_val_list('a string'), from_key_val_list(42), from_key_val_list(True), or from_key_val_list(b'bytes'); passing a scalar where a dict or list-of-tuples is expected.
Common situations: This function is used internally (e.g., in cookie and data encoding). Users typically hit it indirectly by passing a string where a dict is expected to params/data/cookies kwargs; or by calling this utility directly with wrong types.
Related errors
- chunk_size must be an int, it is instead a
- Header part ( ) from must be of type str or bytes, not
- Invalid percent-escape sequence
- You can only send PreparedRequests.
AI-assisted analysis of psf/requests@8068356288 (2026-08-11).
Data as JSON: /api/errors/d97bc89b2dd6e20e.
Report an issue: GitHub.
Appendix: source
Thrown at src/requests/utils.py:365
::
>>> from_key_val_list([('key', 'val')])
OrderedDict([('key', 'val')])
>>> from_key_val_list('string')
Traceback (most recent call last):
...
ValueError: cannot encode objects that are not 2-tuples
>>> from_key_val_list({'key': 'val'})
OrderedDict([('key', 'val')])
:rtype: OrderedDict
"""
if value is None:
return None
if isinstance(value, (str, bytes, bool, int)):
raise ValueError("cannot encode objects that are not 2-tuples")
return OrderedDict(value)
@overload
def to_key_val_list(value: None) -> None: ...
@overload
def to_key_val_list(
value: _t.SupportsItems[_KT, _VT] | Iterable[tuple[_KT, _VT]],
) -> list[tuple[_KT, _VT]]: ...
def to_key_val_list(
value: _t.SupportsItems[_KT, _VT] | Iterable[tuple[_KT, _VT]] | None,
) -> list[tuple[_KT, _VT]] | None:
"""Take an object and test to see if it can be represented as a
dictionary. If it can be, return a list of tuples, e.g.,
::
View on GitHub (pinned to 8068356288)