Skip to content

[BUG] SQLiteFlowPersistence crashes with TypeError when Flow state contains datetime, UUID, or set fields #7358

Description

@Rohitkanithi

Description

When persisting Flow state via @persist or SQLiteFlowPersistence, workflows with structured Pydantic state models containing standard fields like datetime, UUID, set, Decimal, or Path crash during state saving with:

RuntimeError: State persistence failed: Object of type datetime is not JSON serializable

Root Cause:

In lib/crewai/src/crewai/flow/persistence/sqlite.py:

  1. _to_state_dict calls state_data.model_dump() without specifying mode="json". In Pydantic v2, model_dump() keeps native Python types (datetime.datetime, uuid.UUID, set, etc.) instead of converting them to JSON primitives.
  2. In _save_state_sql (line 142) and save_pending_feedback (line 241), json.dumps(state_dict) is called directly without a serializer fallback (default=str), which immediately raises a TypeError on any non-primitive type.

Steps to Reproduce

  1. Define a Flow with a Pydantic state model containing a datetime (or uuid.UUID, set).
  2. Attach SQLiteFlowPersistence using @persist on a flow step.
  3. Call flow.kickoff().
  4. Observe the flow crashing upon completing the persisted method.

Expected behavior

SQLiteFlowPersistence should serialize Pydantic state models in JSON mode (model_dump(mode="json")) and handle fallback dicts gracefully with default=str. When loaded back via load_state, Pydantic's model_validate restores them to their native types (datetime, UUID, set) without data loss.

Screenshots/Code snippets

from datetime import datetime, timezone
import uuid
from pydantic import BaseModel, Field
from crewai.flow.flow import Flow, start
from crewai.flow.persistence import persist, SQLiteFlowPersistence

class WorkflowState(BaseModel):
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
user_id: uuid.UUID = Field(default_factory=uuid.uuid4)
tags: set[str] = Field(default_factory=lambda: {"analytics", "v1"})

persistence = SQLiteFlowPersistence("test_flow.db")

class SampleFlow(Flow[WorkflowState]):
initial_state = WorkflowState

@start()
@persist(persistence)
def step_one(self):
    return "done"

flow = SampleFlow(persistence=persistence)
flow.kickoff()

Operating System

macOS Sonoma

Python Version

3.12

crewAI Version

1.15.20

crewAI Tools Version

1.15.20

Virtual Environment

Venv

Evidence

Failed to persist state for method step_one: Object of type datetime is not JSON serializable
Flow Method Failed

  • Method: step_one
  • Status: Failed

FLOW CRASHED: RuntimeError: State persistence failed: Object of type datetime is not JSON serializable

Possible Solution

  1. In lib/crewai/src/crewai/flow/persistence/sqlite.py: update _to_state_dict to use state_data.model_dump(mode="json"):
@staticmethod
def _to_state_dict(state_data: dict[str, Any] | BaseModel) -> dict[str, Any]:
    """Convert state_data to a plain dict."""
    if isinstance(state_data, BaseModel):
        return state_data.model_dump(mode="json")
    if isinstance(state_data, dict):
        return state_data
    raise ValueError(
        f"state_data must be either a Pydantic BaseModel or dict, got {type(state_data)}"
    )

### Additional context

I have tested the fix locally along with full roundtrip serialization/deserialization verification and unit tests. Ready to submit a PR!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions