django/django · error · DeserializationError

Error deserializing object: {exc}

Error message

Error deserializing object: {exc}

What it means

`Deserializer._handle_object` in the JSON serializer (json.py:75-81) wraps any non-`GeneratorExit`/non-`DeserializationError` exception raised while turning one deserialized dict into a model instance. It re-raises as `DeserializationError(f"Error deserializing object: {exc}")`, chaining the original via `from exc`. This is the catch-all for per-object failures during JSON fixture loading.

Source

Thrown at django/core/serializers/json.py:81

    def __init__(self, stream_or_string, **options):
        if not isinstance(stream_or_string, (bytes, str)):
            stream_or_string = stream_or_string.read()
        if isinstance(stream_or_string, bytes):
            stream_or_string = stream_or_string.decode()
        try:
            objects = json.loads(stream_or_string)
        except Exception as exc:
            raise DeserializationError() from exc
        super().__init__(objects, **options)

    def _handle_object(self, obj):
        try:
            yield from super()._handle_object(obj)
        except (GeneratorExit, DeserializationError):
            raise
        except Exception as exc:
            raise DeserializationError(f"Error deserializing object: {exc}") from exc


class DjangoJSONEncoder(json.JSONEncoder):
    """
    JSONEncoder subclass that knows how to encode date/time, decimal types, and
    UUIDs.
    """

    def default(self, o):
        # See "Date Time String Format" in the ECMA-262 specification.
        if isinstance(o, datetime.datetime):
            r = o.isoformat(
                sep="T",
                timespec="milliseconds" if o.microsecond // 1000 else "seconds",
            )
            if r.endswith("+00:00"):
                r = r.removesuffix("+00:00") + "Z"
            return r

View on GitHub (pinned to b5388a3a80)

Solutions

  1. Read the chained `__cause__` exception to find the real failure (field name, model, value).
  2. Load with `ignorenonexistent=True` to skip fields/objects that no longer match the model.
  3. Re-export the fixture from a schema matching the target model definitions.
  4. If a FK target is missing, load the referenced fixture first or use `handle_forward_references=True`.

Example fix

// before
for obj in serializers.deserialize('json', payload):
    obj.save()  # DeserializationError: Error deserializing object: ...
// after
try:
    for obj in serializers.deserialize('json', payload, ignorenonexistent=True):
        obj.save()
except DeserializationError as exc:
    raise RuntimeError('fixture row failed: %r', exc.__cause__) from exc
Defensive patterns

Strategy: try-catch

Validate before calling

import json
from django.core import serializers
from django.core.serializers.base import DeserializationError

def safe_load_json(payload):
    try:
        objects = json.loads(payload)
    except ValueError as e:
        raise ValueError(f'invalid JSON document: {e}')
    if not isinstance(objects, list):
        raise ValueError('expected a JSON list of objects')
    return objects

Try / catch

from django.core.serializers.base import DeserializationError
try:
    for obj in serializers.deserialize('json', payload, ignorenonexistent=True):
        obj.save()
except DeserializationError as exc:
    # exc.__cause__ holds the real failure; exc.args[0] is the wrapped message
    raise RuntimeError(f'JSON object failed: {exc}') from exc.__cause__

Prevention

When it happens

Trigger: Loading JSON fixture data where an individual object dict references an unknown model, a field value fails `to_python()` conversion, a FK/M2M lookup misses, or `build_instance` raises. The wrapping happens after `json.loads` succeeded, so the JSON itself was syntactically valid.

Common situations: Fixture exported from an older Django with fields since removed from the model; a CharField value that fails validation/conversion (e.g. bad date string); a ContentType or natural-key target missing in the target DB; model moved/renamed between apps.

Related errors


AI-assisted analysis of django/django@b5388a3a80 (2026-08-10). Data as JSON: /api/errors/7475f887b33f0089. Report an issue: GitHub.