PrefectHQ/fastmcp · error · TypeError
Value for state key {key!r} is not serializable. Use set_sta
Error message
Value for state key {key!r} is not serializable. Use set_state({key!r}, value, serializable=False) to store non-serializable values. Note: non-serializable state is request-scoped and will not persist across requests. What it means
Context.set_state() serializes values (via pydantic) before storing them in the key-value store. When pydantic raises a serialization ValueError, set_state converts it into this TypeError telling you to pass serializable=False. Non-serializable state is still allowed but is request-scoped and will not persist across requests.
Source
Thrown at fastmcp_slim/fastmcp/server/context.py:1143
The key is automatically prefixed with the session identifier.
"""
prefixed_key = self._make_state_key(key)
if not serializable:
self._request_state[prefixed_key] = value
return
# Clear any request-scoped shadow so the session value is visible
self._request_state.pop(prefixed_key, None)
try:
await self.fastmcp._state_store.put(
key=prefixed_key,
value=StateValue(value=value),
ttl=self._STATE_TTL_SECONDS,
)
except ValueError as e:
# Pydantic raises PydanticSerializationError (a ValueError) and the
# message carries "serialize". Other ValueErrors propagate unchanged.
if "serialize" in str(e).lower():
raise TypeError(
f"Value for state key {key!r} is not serializable. "
f"Use set_state({key!r}, value, serializable=False) to store "
f"non-serializable values. Note: non-serializable state is "
f"request-scoped and will not persist across requests."
) from e
raise
except Exception as e:
# Import the optional storage implementation only on its error path,
# rather than adding the key_value package to every server startup.
from key_value.aio.errors import SerializationError
if not isinstance(e, SerializationError):
raise
raise TypeError(
f"Value for state key {key!r} is not serializable. "
f"Use set_state({key!r}, value, serializable=False) to store "
f"non-serializable values. Note: non-serializable state is "
f"request-scoped and will not persist across requests."View on GitHub (pinned to 1f02114297)
Solutions
- Pass serializable=False if the value only needs to live for the current request: ctx.set_state(key, value, serializable=False).
- Otherwise store a serializable representation (dict of primitives, JSON string) and reconstruct the object on read.
- For objects needing custom serialization, add a model serializer or convert to a supported type before storing.
Example fix
// before
await ctx.set_state("engine", engine)
// after
await ctx.set_state("engine", engine, serializable=False) # request-scoped
// or persist data instead:
await ctx.set_state("engine_dsn", engine.url) Defensive patterns
Strategy: validation
Validate before calling
import pydantic
try:
pydantic.TypeAdapter(Any).dump_python(value)
serializable = True
except Exception:
serializable = False
await ctx.set_state(key, value, serializable=not serializable and needs_request_scope) Try / catch
try:
await ctx.set_state(key, value)
except TypeError as e:
if "not serializable" in str(e):
await ctx.set_state(key, value, serializable=False)
else:
raise Prevention
- Store only JSON-compatible values in persistent state
- Use serializable=False knowingly for request-scoped objects
- Add a unit test asserting every state key you use round-trips
When it happens
Trigger: ctx.set_state(key, value) where value cannot be pydantic-serialized (e.g. an open file handle, a lock, a custom object without serialization support) and serializable is not set to False.
Common situations: Storing database connections, asyncio primitives, or dataclass instances in server state; refactoring code that previously kept such objects in module globals into Context state.
Related errors
- The API key is empty
- The Horizon API key is invalid
- CLI state is invalid: {path.name}
- Could not write CLI state: {path.name}
- At least one of 'tools', 'include_tags', or 'exclude_tags' i
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/7c44cd0a8762429b.
Report an issue: GitHub.