psf/requests · error · InvalidJSONError
{ve}
Error message
{ve} What it means
Raised by PreparedRequest.prepare_body when json.dumps fails on the supplied json= argument. The default dumps is called with allow_nan=False, so NaN/Infinity (which are invalid per strict JSON) always trigger this; any other ValueError from the encoder (circular references via a custom encoder, non-serializable types) is also wrapped as InvalidJSONError. This signals that the request body could not be produced.
Source
Thrown at src/requests/models.py:596
) -> None:
"""Prepares the given HTTP body data."""
# Check if file, fo, generator, iterator.
# If not, run through normal process.
# Nottin' on you.
body = None
content_type = None
if not data and json is not None:
# urllib3 requires a bytes-like body. Python 2's json.dumps
# provides this natively, but Python 3 gives a Unicode string.
content_type = "application/json"
try:
body = complexjson.dumps(json, allow_nan=False)
except ValueError as ve:
raise InvalidJSONError(ve, request=self)
if not isinstance(body, bytes):
body = body.encode("utf-8")
# data that proxies attributes to underlying objects needs hasattr
is_iterable = isinstance(data, Iterable) or hasattr(data, "__iter__")
if is_iterable and not isinstance(data, (str, bytes, list, tuple, Mapping)):
try:
length = super_len(data)
except (TypeError, AttributeError, UnsupportedOperation):
length = None
body = data
if getattr(body, "tell", None) is not None:
# Record the current file position before reading.
# This will allow us to rewind a file in the event
# of a redirect.View on GitHub (pinned to 8068356288)
Solutions
- Sanitize NaN/Inf values before passing json= (replace with None or a string), or post-process with a custom serializer.
- For non-serializable types, convert to plain dicts/lists first, or use a json= argument that is already a str produced by your own dumps with a default hook.
- Catch InvalidJSONError and either serialize manually or fail the request gracefully.
Example fix
// before
import math
payload = {'ratio': float('nan')}
requests.post(url, json=payload)
// after
import math
payload = {'ratio': None if math.isnan(r) else r for r in [...]}
requests.post(url, json=payload) Defensive patterns
Strategy: validation
Validate before calling
import json, math, requests
def json_safe(obj):
if isinstance(obj, float) and (math.isnan(obj) or math.isinf(obj)):
return None
if isinstance(obj, dict):
return {k: json_safe(v) for k, v in obj.items()}
if isinstance(obj, (list, tuple)):
return [json_safe(v) for v in obj]
return obj Type guard
import math
def is_json_safe(obj) -> bool:
if isinstance(obj, float):
return not (math.isnan(obj) or math.isinf(obj))
if isinstance(obj, dict):
return all(is_json_safe(v) for v in obj.values())
if isinstance(obj, (list, tuple)):
return all(is_json_safe(v) for v in obj)
return obj is None or isinstance(obj, (str, int, bool)) Try / catch
from requests.exceptions import InvalidJSONError
try:
resp = requests.post(url, json=payload)
except InvalidJSONError:
# sanitize and retry, or serialize manually
resp = requests.post(url, data=json.dumps(payload, default=str)) Prevention
- Sanitize NaN/Inf in numeric payloads before passing json=.
- Convert non-serializable objects (datetime, set, custom) to primitives first.
- Register a default= hook if you must serialize complex types.
When it happens
Trigger: Passing json=float('nan') or json=float('inf') (rejected by allow_nan=False); passing a non-serializable object (datetime, set, custom class) without a default= hook; circular references in nested structures.
Common situations: Logging/metrics payloads containing NaN from numeric processing; ORM objects or dataclasses not registered with a JSON encoder; third-party objects that look dict-like but aren't serializable.
Related errors
- Auth hooks must be callable.
- Cookie headers should be added with add_unredirected_header(
- name={name!r}, domain={domain!r}, path={path!r}
- There are multiple cookies with name, {name!r}
- {e.args}
AI-assisted analysis of psf/requests@8068356288 (2026-08-11).
Data as JSON: /api/errors/21533145d34fbe17.
Report an issue: GitHub.