PersistenceDecorator.persist_state raises wrong error message when Flow state is None
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 58.8k
- Forks
- 8.5k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 109
Description
PersistenceDecorator.persist_state in lib/crewai/src/crewai/flow/persistence/decorators.py raises the wrong error message when a Flow instance has no state at all, because the two ValueErrors it can raise internally are mapped to the wrong except clause.
The method has this structure (lines 94-144):
try:
state = getattr(flow_instance, "state", None)
if state is None:
raise ValueError("Flow instance has no state")
flow_uuid: str | None = None
if isinstance(state, dict):
flow_uuid = state.get("id")
elif hasattr(state, "_unwrap"):
...
elif isinstance(state, BaseModel) or hasattr(state, "id"):
flow_uuid = getattr(state, "id", None)
if not flow_uuid:
raise ValueError("Flow state must have an 'id' field for persistence")
...
try:
...
persistence_instance.save_state(...)
except Exception as e:
...
raise RuntimeError(f"State persistence failed: {e!s}") from e
except AttributeError as e:
error_msg = LOG_MESSAGES["state_missing"]
...
raise ValueError(error_msg) from e
except (TypeError, ValueError) as e:
error_msg = LOG_MESSAGES["id_missing"]
...
raise ValueError(error_msg) from e
LOG_MESSAGES defines:
LOG_MESSAGES: Final[dict[str, str]] = {
"save_state": "Saving flow state to memory for ID: {}",
"save_error": "Failed to persist state for method {}: {}",
"state_missing": "Flow instance has no state",
"id_missing": "Flow state must have an 'id' field for persistence",
}
The "no state" case is raised as a ValueError at line 97 (raise ValueError("Flow instance has no state")), but ValueError is only caught by the second except clause, except (TypeError, ValueError), whose handler always uses LOG_MESSAGES["id_missing"]. The first except clause, except AttributeError, is the one associated with LOG_MESSAGES["state_missing"], but nothing in the try block ever raises a plain AttributeError for the "no state" condition (getattr(flow_instance, "state", None) cannot raise AttributeError since it passes a default).
So the two error paths are swapped: whenever a Flow instance has state is None, the exception that reaches the caller (and gets logged/printed) is:
ValueError: Flow state must have an 'id' field for persistence
instead of the correct:
ValueError: Flow instance has no state
This is misleading during debugging: someone whose Flow simply has no state attribute set will be told to check for a missing 'id' field, which is not the actual problem.
Repro:
from types import SimpleNamespace
from crewai.flow.persistence.decorators import PersistenceDecorator
from crewai.flow.persistence.sqlite import SQLiteFlowPersistence
flow_instance = SimpleNamespace(state=None)
PersistenceDecorator.persist_state(flow_instance, "some_method", SQLiteFlowPersistence())
Expected: ValueError: Flow instance has no state
Actual: ValueError: Flow state must have an 'id' field for persistence
Fix direction: swap the message assignment so the ValueError raised at line 97 maps to state_missing and the one at line 112 maps to id_missing (e.g. by raising distinct exception types, or by inspecting str(e) / using a single except clause that checks which condition triggered it, rather than relying on exception-type dispatch across two ValueError raise sites).
Duplicate-checked: searched repo:crewAIInc/crewAI is:issue persist_state ValueError, PersistenceDecorator, persist error message, and flow persistence id field — no existing issue describes this.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read persist_state in lib/crewai/src/crewai/flow/persistence/decorators.py, focusing on lines 94-144 and its two ValueError paths. Run the provided SimpleNamespace and SQLiteFlowPersistence reproduction, then verify that a missing state reports "Flow instance has no state" while a missing id reports "Flow state must have an 'id' field for persistence".
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, sqlite
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100