pallets/flask · error · TypeError

Object of type {type(o).__name__} is not JSON serializable

Error message

Object of type {type(o).__name__} is not JSON serializable

What it means

Raised by Flask's DefaultJSONProvider fallback serializer (`_default` in src/flask/json/provider.py) when an object reaches the end of its type-conversion chain. Flask extends stdlib json with support for date/datetime (RFC 822 strings), Decimal, UUID, dataclasses, and objects with `__html__` (Markup); anything else raises this TypeError because Python's `json.dumps` has no representation for it.

Source

Thrown at src/flask/json/provider.py:121

        """
        obj = self._prepare_response_obj(args, kwargs)
        return self._app.response_class(self.dumps(obj), mimetype="application/json")


def _default(o: t.Any) -> t.Any:
    if isinstance(o, date):
        return http_date(o)

    if isinstance(o, (decimal.Decimal, uuid.UUID)):
        return str(o)

    if dataclasses and dataclasses.is_dataclass(o):
        return dataclasses.asdict(o)  # type: ignore[arg-type]

    if hasattr(o, "__html__"):
        return str(o.__html__())

    raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable")


class DefaultJSONProvider(JSONProvider):
    """Provide JSON operations using Python's built-in :mod:`json`
    library. Serializes the following additional data types:

    -   :class:`datetime.datetime` and :class:`datetime.date` are
        serialized to :rfc:`822` strings. This is the same as the HTTP
        date format.
    -   :class:`uuid.UUID` is serialized to a string.
    -   :class:`dataclasses.dataclass` is passed to
        :func:`dataclasses.asdict`.
    -   :class:`~markupsafe.Markup` (or any object with a ``__html__``
        method) will call the ``__html__`` method to get a string.
    """

    default: t.Callable[[t.Any], t.Any] = staticmethod(_default)
    """Apply this function to any object that :meth:`json.dumps` does

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Convert the offending object to a JSON-native type before jsonify: `list(my_set)`, `my_bytes.decode()`, `int(np_value)`, or a dict via a `to_dict()` method / marshmallow / pydantic `.model_dump()`.
  2. Subclass DefaultJSONProvider, override `default()` to handle your types, and set `app.json = MyProvider(app)` (Flask 2.2+).
  3. For dataclass-like models, define the model as a `@dataclass` or give it a `__html__`-free `to_dict()` and serialize that.
  4. On Flask <2.2, set `app.json_encoder` to a custom `json.JSONEncoder` subclass instead.

Example fix

# before
return jsonify({"ids": {1, 2, 3}})  # TypeError: Object of type set is not JSON serializable

# after
return jsonify({"ids": sorted({1, 2, 3})})

# or globally (Flask 2.2+):
class MyJSONProvider(DefaultJSONProvider):
    @staticmethod
    def default(o):
        if isinstance(o, set):
            return list(o)
        return DefaultJSONProvider.default(o)
app.json = MyJSONProvider(app)
Defensive patterns

Strategy: validation

Validate before calling

import json
def is_json_safe(obj):
    try:
        json.dumps(obj, default=str)  # probe
        return True
    except TypeError:
        return False
# Better: convert before passing to jsonify
from dataclasses import asdict, is_dataclass
payload = asdict(obj) if is_dataclass(obj) else obj

Type guard

def is_serializable(o):
    return isinstance(o, (dict, list, tuple, str, int, float, bool, type(None)))

Try / catch

try:
    return jsonify(data)
except TypeError:
    app.logger.exception('non-serializable payload')
    return jsonify({'error': 'internal serialization error'}), 500

Prevention

When it happens

Trigger: Calling `jsonify(obj)`, `flask.json.dumps(obj)`, or returning a dict/list from a view that contains an unsupported type — e.g. a set, bytes, a generator, a SQLAlchemy model instance, a numpy int64/float32/ndarray, a custom class, or a Decimal-wrapping proxy that isn't one of the handled types.

Common situations: Returning SQLAlchemy ORM objects or query results directly from a route; passing numpy/pandas values from data-science code into jsonify; serializing sets built for dedup; returning bytes from crypto/file APIs; after upgrading to Flask 2.2+ where the custom-JSONEncoder pattern (`app.json_encoder`) was deprecated in favor of providers, breaking old custom encoders.

Related errors


AI-assisted analysis of pallets/flask@6a2f545bfd (2026-07-31). Data as JSON: /data/errors/d69686dda339bade.json. Report an issue: GitHub ↗.