apache/superset · error · KeyValueCreateFailedError
Unable to encode value
Error message
Unable to encode value
What it means
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.
Source
Thrown at superset/daos/key_value.py:116
) -> KeyValueEntry:
"""
Create a new entry in the key-value store.
.. note::
This method intentionally does **not** purge expired entries. Callers
that pass an explicit ``key`` along with an ``expires_on`` must call
:meth:`delete_expired_entries` for the same ``resource`` once before
creating their entries. Purging is deliberately hoisted out of this
method so that a transaction creating many entries pays the cleanup cost
only once up front rather than on every insert. An expired entry still
occupying the same ``key`` would otherwise cause this insert to fail the
unique constraint. (Entries created without an explicit ``key`` get an
auto-generated id and cannot collide, so they need no prior purge.)
"""
try:
encoded_value = codec.encode(value)
except Exception as ex:
raise KeyValueCreateFailedError("Unable to encode value") from ex
entry = KeyValueEntry(
resource=resource.value,
value=encoded_value,
created_on=datetime.now(),
created_by_fk=get_user_id(),
expires_on=expires_on,
)
if key is not None:
try:
if isinstance(key, UUID):
entry.uuid = key
else:
entry.id = key
except ValueError as ex:
raise KeyValueCreateFailedError() from ex
db.session.add(entry)
return entry
View on GitHub (pinned to f4587218dd)
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.
Example fix
# before
KeyValueDAO.create_entry(resource, value={'ts': datetime.now()}, codec=JsonCodec())
# -> KeyValueCreateFailedError('Unable to encode value')
# after
from json import JSONEncoder
class SafeEncoder(JSONEncoder):
def default(self, o):
if isinstance(o, (datetime, date)):
return o.isoformat()
return super().default(o)
value = json.loads(json.dumps(value, cls=SafeEncoder))
KeyValueDAO.create_entry(resource, value=value, codec=JsonCodec()) Defensive patterns
Strategy: validation
Validate before calling
import json
from datetime import date, datetime
from decimal import Decimal
def json_safe(value):
return json.loads(json.dumps(value, default=lambda o: o.isoformat() if isinstance(o, (datetime, date)) else str(o)))
# use: KeyValueDAO.create_entry(resource, json_safe(payload), JsonCodec()) Type guard
def is_json_safe(v: object) -> bool:
try:
json.dumps(v)
return True
except TypeError:
return False Try / catch
from superset.daos.key_value import KeyValueDAO
from superset.key_value.commands.exceptions import KeyValueCreateFailedError
try:
entry = KeyValueDAO.create_entry(resource, value, codec, key=key)
except KeyValueCreateFailedError as err:
cause = err.__cause__ # original codec exception — inspect it
log.warning('encode failed: %r', cause) Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- An error occurred while creating the value.
- An error occurred while updating the value.
- CSS template not found.
- An error occurred while accessing the value.
- Unexpected missing key id
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/6accb083f31acaa4.
Report an issue: GitHub.