{"record":{"id":"653fe5dd9cd19fc8","repo":"keras-team/keras","slug":"unable-to-serialize-obj-to-json-unrecognized-ty","errorCode":null,"errorMessage":"Unable to serialize {obj} to JSON. Unrecognized type {type(obj)}.","messagePattern":"Unable to serialize (.+?) to JSON\\. Unrecognized type (.+?)\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"keras/src/legacy/saving/json_utils.py","lineNumber":218,"sourceCode":"            )\n    if tf.available and isinstance(obj, tf.__internal__.CompositeTensor):\n        spec = tf.type_spec_from_value(obj)\n        tensors = []\n        for tensor in tf.nest.flatten(obj, expand_composites=True):\n            tensors.append((tensor.dtype.name, tensor.numpy().tolist()))\n        return {\n            \"class_name\": \"CompositeTensor\",\n            \"spec\": get_json_type(spec),\n            \"tensors\": tensors,\n        }\n\n    if isinstance(obj, enum.Enum):\n        return obj.value\n\n    if isinstance(obj, bytes):\n        return {\"class_name\": \"__bytes__\", \"value\": obj.decode(\"utf-8\")}\n\n    raise TypeError(\n        f\"Unable to serialize {obj} to JSON. Unrecognized type {type(obj)}.\"\n    )\n","sourceCodeStart":200,"sourceCodeEnd":221,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/legacy/saving/json_utils.py#L200-L221","documentation":"get_json_type is the fallback serializer behind model.to_json(); after handling dicts, lists, tuples, numpy scalars, enums, and bytes, any unrecognized object type raises this TypeError naming the object and its type. It is the catch-all for 'this config value cannot be written as JSON'.","triggerScenarios":"model.to_json() when a layer's config holds a non-JSON value: a custom class instance, a function reference, or a type the serializer never learned.","commonSituations":"Custom layers whose get_config returns arbitrary Python objects; passing callables or non-primitive constants as layer arguments.","solutions":["Locate the object named in the message and convert it to a primitive in the custom layer's get_config","Ensure custom get_config returns only str/int/float/bool/list/dict values","Use model.save('model.keras'), which supports richer Python objects"],"exampleFix":"# before\nclass MyLayer(layers.Layer):\n    def get_config(self):\n        return {'fn': self._fn}  # callable -> TypeError\n# after\n    def get_config(self):\n        return {'fn_name': self._fn.__name__}","handlingStrategy":"validation","validationCode":"import json\ncfg = layer.get_config()\njson.dumps(cfg)  # dry-run: raises before saving if non-serializable","typeGuard":"def config_json_safe(cfg):\n    try:\n        json.dumps(cfg)\n        return True\n    except TypeError:\n        return False","tryCatchPattern":"try:\n    model.to_json()\nexcept TypeError as e:\n    if 'Unrecognized type' not in str(e):\n        raise\n    model.save('model.keras')","preventionTips":["Unit-test custom get_config with a json.dumps round-trip"],"tags":["keras","serialization","json","custom-layers"],"backgroundTag":"json-serialization-failed","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}