deepset-ai/haystack · error · ValueError
State: Key '{key}' not found in schema. Schema: {self.schema
Error message
State: Key '{key}' not found in schema. Schema: {self.schema} What it means
State.set raises this ValueError when the key being written is not present in the State's schema. The schema is closed: only keys declared at construction can be set, which keeps merges deterministic.
Source
Thrown at haystack/components/agents/state/state.py:169
"""
return deepcopy(self._data.get(key, default))
def set(self, key: str, value: Any, handler_override: Callable[[Any, Any], Any] | None = None) -> None:
"""
Set or merge a value in the state according to schema rules.
Value is merged or overwritten according to these rules:
- if handler_override is given, use that
- else use the handler defined in the schema for 'key'
:param key: Key to store the value under
:param value: Value to store or merge
:param handler_override: Optional function to override the default merge behavior
"""
# If key not in schema, we throw an error
definition = self.schema.get(key, None)
if definition is None:
raise ValueError(f"State: Key '{key}' not found in schema. Schema: {self.schema}")
# Get current value from state and apply handler
current_value = self._data.get(key, None)
handler = handler_override or definition["handler"]
self._data[key] = handler(current_value, value)
@property
def data(self) -> dict[str, Any]:
"""
All current data of the state.
"""
return self._data
def has(self, key: str) -> bool:
"""
Check if a key exists in the state.
:param key: Key to check for existenceView on GitHub (pinned to e318778c9b)
Solutions
- Add the missing key to the state schema, e.g. {"foo": {"type": list}}
- Check tool output {"state_key": ...} mappings against the schema keys
- If the key shouldn't persist, return it only in the tool's string output instead of merging into state
Example fix
// before
agent = Agent(..., state_schema={"messages": {"type": list[ChatMessage]}})
# tool writes state_key="results"
// after
agent = Agent(..., state_schema={"messages": {"type": list[ChatMessage]}, "results": {"type": list}}) Defensive patterns
Strategy: validation
Validate before calling
def keys_in_schema(keys, schema):
missing = [k for k in keys if k not in schema]
if missing:
raise KeyError(f"Keys not in schema: {missing}") Type guard
def key_is_declared(key, schema) -> bool:
return key in schema Try / catch
try:
state.set(key, value)
except ValueError as e:
if "not found in schema" in str(e):
state = State({**state.schema, key: {"type": type(value), "handler": None}}, state._data)
state.set(key, value)
else:
raise Prevention
- Keep tool outputs_to_state keys and state_schema keys in sync; test them together
- Before adding a schema key, grep tool configs for the state_key
- Add a startup assertion that all tool state keys exist in the schema
When it happens
Trigger: Calling state.set("foo", value) where 'foo' was not declared in the schema passed to State/Agent; a tool output mapping writing an undeclared key; state_schema omitting a key that tools emit.
Common situations: Adding a new tool whose output mapping targets a state key not added to the Agent's state_schema, or renaming a schema key without updating tool configs.
Related errors
- StateSchema: Key '{param}' is missing a 'type' entry.
- StateSchema: 'type' for key '{param}' must be a Python type,
- StateSchema: 'handler' for key '{param}' must be callable or
- StateSchema: 'messages' must be of type list[ChatMessage], g
- Tool '{tool.name}': failed to merge outputs into state. {e}
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/166411688696d83d.
Report an issue: GitHub.