[BUG] Shared serializer turns Enum values into repr strings

Open Beginner friendly
#7,652 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
84/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
backend

Research direction

Start in crewai/utilities/serialization.py by reading to_serializable() and _to_serializable_key(), then inspect flow/runtime/_outputs.py and safe_serialize_to_dict() for their serializer usage. Run the offline reproduction from the issue and confirm that Enum, IntEnum, date-valued, tuple-valued, and dictionary-key cases preserve their declared values without repr strings or object ids.

Written by the indexing model from the issue text.

Description

Description

crewai.utilities.serialization.to_serializable() has no Enum branch, so any plain Enum value falls through to the repr() fallback. A string-valued enum such as Status.OK = "ok" is serialized as "<Status.OK: 'ok'>" instead of "ok".

This is not cosmetic. The shared serializer backs Flow expression outputs (flow/runtime/_outputs.py) and trace event conversion (safe_serialize_to_dict()), so an enum emitted by a flow method or included in trace data loses its declared wire value. IntEnum values currently pass through the int branch and keep their value only by accident of inheritance.

Enum values used as dictionary keys are also unstable: _to_serializable_key() produces a string containing the object id(), for example key_4383468448_<Key.X: 'x'>, which changes between runs.

This report was prepared with AI assistance. I cannot apply repository labels as an external contributor; please add the required llm-generated label.

Steps to reproduce

from enum import Enum
from crewai.utilities.serialization import to_serializable

class Status(Enum):
    OK = "ok"

assert to_serializable({"status": Status.OK}) == {"status": "ok"}
# AssertionError: actual value is {"status": "<Status.OK: 'ok'>"}

Expected behavior

Enums should serialize to their declared .value consistently, for both values and dictionary keys. IntEnum, date-valued, and tuple-valued enums should recurse through the same value path so they keep their intended semantics.

Screenshots/Code snippets

The serializer handles primitives, UUIDs, dates, collections, dataclasses, and Pydantic models, then defaults everything else to repr(obj). Enum is missing between the primitive check and the fallback.

Operating System

macOS Sonoma

Python Version

3.13 (supported by the repository; not listed in the issue template)

crewAI Version

Current main (0374c631297f)

crewAI Tools Version

Current main (0374c631297f)

Virtual Environment

Venv (uv)

Evidence

A deterministic offline reproduction fails on current main and passes once Enum expands to to_serializable(obj.value) before the primitive check, with _to_serializable_key() doing the same for keys.

Possible Solution

Handle Enum first in to_serializable() by recursing into obj.value, and mirror that in _to_serializable_key().

Additional context

Closed, unmerged PR #5180 contained a similar enum-value fix inside a much broader tracing change; it was closed stale with maintainers inviting a focused follow-up. This issue scopes only the enum contract in the shared serializer.

Dominant language
Python
Stars
58.8k
Forks
8.5k
Avg merge
1d 13h
Merged PRs (30d)
103

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from crewAIInc/crewAI

All issues in crewAIInc/crewAI

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.