{"record":{"id":"6accb083f31acaa4","repo":"apache/superset","slug":"unable-to-encode-value","errorCode":null,"errorMessage":"Unable to encode value","messagePattern":"Unable to encode value","errorType":"exception","errorClass":"KeyValueCreateFailedError","httpStatus":500,"severity":"error","filePath":"superset/daos/key_value.py","lineNumber":116,"sourceCode":"    ) -> KeyValueEntry:\n        \"\"\"\n        Create a new entry in the key-value store.\n\n        .. note::\n            This method intentionally does **not** purge expired entries. Callers\n            that pass an explicit ``key`` along with an ``expires_on`` must call\n            :meth:`delete_expired_entries` for the same ``resource`` once before\n            creating their entries. Purging is deliberately hoisted out of this\n            method so that a transaction creating many entries pays the cleanup cost\n            only once up front rather than on every insert. An expired entry still\n            occupying the same ``key`` would otherwise cause this insert to fail the\n            unique constraint. (Entries created without an explicit ``key`` get an\n            auto-generated id and cannot collide, so they need no prior purge.)\n        \"\"\"\n        try:\n            encoded_value = codec.encode(value)\n        except Exception as ex:\n            raise KeyValueCreateFailedError(\"Unable to encode value\") from ex\n        entry = KeyValueEntry(\n            resource=resource.value,\n            value=encoded_value,\n            created_on=datetime.now(),\n            created_by_fk=get_user_id(),\n            expires_on=expires_on,\n        )\n        if key is not None:\n            try:\n                if isinstance(key, UUID):\n                    entry.uuid = key\n                else:\n                    entry.id = key\n            except ValueError as ex:\n                raise KeyValueCreateFailedError() from ex\n        db.session.add(entry)\n        return entry\n","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/daos/key_value.py#L98-L134","documentation":"Raised by KeyValueDAO.create_entry when codec.encode(value) throws for any reason. The key-value store is generic: callers pick a KeyValueCodec (e.g. JsonCodec, PickleCodec) per resource, and if the value is not serializable by that codec the encode step fails and is wrapped in KeyValueCreateFailedError ('Unable to encode value'). Typical cause: JSON codec receiving a value containing datetime, Decimal, set, or arbitrary objects.","triggerScenarios":"Storing chart/dashboard tab state or any payload containing datetime.datetime or Decimal objects through a JsonCodec-based resource; storing ORM model instances or numpy types with a codec that cannot pickle them; a custom codec whose encode() raises on unexpected input shapes.","commonSituations":"Chart data payloads built from pandas/sqlalchemy rows that carry Decimal or Timestamp values; switching a resource's codec (pickle -> json) without migrating stored-value expectations; frontend tab state containing non-JSON-serializable values injected server-side.","solutions":["Inspect the exception's __cause__ (the original codec exception) to see exactly which value failed to encode.","Convert non-serializable values before storing: str()/float() for datetimes and Decimals, or add a custom json.JSONEncoder default handler.","Pick a codec that matches your data: PickleCodec for rich Python objects, JsonCodec only for plain JSON-safe structures.","Add a unit test that round-trips your payload through codec.encode/decode before wiring it into KeyValueDAO."],"exampleFix":"# before\nKeyValueDAO.create_entry(resource, value={'ts': datetime.now()}, codec=JsonCodec())\n# -> KeyValueCreateFailedError('Unable to encode value')\n\n# after\nfrom json import JSONEncoder\nclass SafeEncoder(JSONEncoder):\n    def default(self, o):\n        if isinstance(o, (datetime, date)):\n            return o.isoformat()\n        return super().default(o)\nvalue = json.loads(json.dumps(value, cls=SafeEncoder))\nKeyValueDAO.create_entry(resource, value=value, codec=JsonCodec())","handlingStrategy":"validation","validationCode":"import json\nfrom datetime import date, datetime\nfrom decimal import Decimal\n\ndef json_safe(value):\n    return json.loads(json.dumps(value, default=lambda o: o.isoformat() if isinstance(o, (datetime, date)) else str(o)))\n\n# use: KeyValueDAO.create_entry(resource, json_safe(payload), JsonCodec())","typeGuard":"def is_json_safe(v: object) -> bool:\n    try:\n        json.dumps(v)\n        return True\n    except TypeError:\n        return False","tryCatchPattern":"from superset.daos.key_value import KeyValueDAO\nfrom superset.key_value.commands.exceptions import KeyValueCreateFailedError\ntry:\n    entry = KeyValueDAO.create_entry(resource, value, codec, key=key)\nexcept KeyValueCreateFailedError as err:\n    cause = err.__cause__  # original codec exception — inspect it\n    log.warning('encode failed: %r', cause)","preventionTips":["Round-trip payloads through the chosen codec in a unit test before wiring into KeyValueDAO.","Convert datetimes/Decimals to primitives at the boundary where the payload is built.","Match codec to data: JsonCodec for plain data, PickleCodec only when Python objects must survive."],"tags":["key-value","serialization","codec","dao"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}