crewai - ✅(Solved) Fix [BUG] Pydantic Validation error while saving in Memory [5 pull requests, 11 comments, 4 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
crewAIInc/crewAI#4509Fetched 2026-04-08 00:41:42
View on GitHub
Comments
11
Participants
4
Timeline
36
Reactions
0
Timeline (top)
commented ×11referenced ×8cross-referenced ×7mentioned ×3

Getting the following Pydantic error while saving to memory.

ERROR:root:OpenAI API call failed: 1 validation error for TaskEvaluation
  Invalid JSON: expected value at line 1 column 1 [type=json_invalid, input_value='```json\n{\n  "assessmen...  ]\n    }\n  ]\n}\n```', input_type=str]
    For further information visit https://errors.pydantic.dev/2.11/v/json_invalid
[2026-02-18 18:17:49][ERROR]: Failed to add to long term memory: Failed to convert text into a Pydantic model due to validation error: 1 validation error for TaskEvaluation
  Invalid JSON: expected value at line 1 column 1 [type=json_invalid, input_value='```json\n{\n  "assessmen...  ]\n    }\n  ]\n}\n```', input_type=str]
    For further information visit https://errors.pydantic.dev/2.11/v/json_invalid
<img width="959" height="640" alt="Image" src="https://github.com/user-attachments/assets/14647808-9760-44bb-af9d-5eebcf9da4cb" />

Error Message

ERROR:root:OpenAI API call failed: 1 validation error for TaskEvaluation Invalid JSON: expected value at line 1 column 1 [type=json_invalid, input_value='

Root Cause

Getting the following Pydantic error while saving to memory.

ERROR:root:OpenAI API call failed: 1 validation error for TaskEvaluation
  Invalid JSON: expected value at line 1 column 1 [type=json_invalid, input_value='```json\n{\n  "assessmen...  ]\n    }\n  ]\n}\n```', input_type=str]
    For further information visit https://errors.pydantic.dev/2.11/v/json_invalid
[2026-02-18 18:17:49][ERROR]: Failed to add to long term memory: Failed to convert text into a Pydantic model due to validation error: 1 validation error for TaskEvaluation
  Invalid JSON: expected value at line 1 column 1 [type=json_invalid, input_value='```json\n{\n  "assessmen...  ]\n    }\n  ]\n}\n```', input_type=str]
    For further information visit https://errors.pydantic.dev/2.11/v/json_invalid
<img width="959" height="640" alt="Image" src="https://github.com/user-attachments/assets/14647808-9760-44bb-af9d-5eebcf9da4cb" />

Fix Action

Fixed

PR fix notes

PR #4510: Fix #4509: Strip markdown code-block fences from LLM JSON responses in Converter

Description (problem / solution / changelog)

Fix #4509: Strip markdown code-block fences from LLM JSON responses

Summary

Some LLMs wrap their JSON responses in markdown code-block fences (```json ... ```), which causes model_validate_json() to fail with a Pydantic validation error. This manifests as "Failed to add to long term memory" errors when memory is enabled.

The fix adds a _strip_markdown_fences() helper that removes these delimiters before JSON parsing, applied in three locations within converter.py:

  • Converter.to_pydantic() — function-calling path
  • Converter.to_pydantic() — non-function-calling path
  • convert_to_model() — before json.loads()

Additionally, the function-calling path now has a handle_partial_json() fallback (previously only present in the non-function-calling path), and the except clauses now catch ValueError alongside ValidationError since model_validate_json can raise either.

11 new unit tests cover the helper function, both converter paths, the TaskEvaluation model, and convert_to_model.

Review & Testing Checklist for Human

  • Regex edge cases: The fence pattern requires a \n before the closing ```. Verify this matches all real-world LLM outputs (e.g., some models may omit the trailing newline before closing fences).
  • Fallback chain in function-calling path: When handle_partial_json is called with agent=None and regex extraction fails, it will fall through to convert_with_instructions() which raises TypeError. This is caught by the outer retry loop, but the error message could be confusing. Consider whether this needs a cleaner error path.
  • Widened except clause: (ValidationError, ValueError) — confirm no legitimate errors are being silently swallowed that should propagate.
  • End-to-end verification: Run the reproduction script from the issue with memory=True against a real LLM that wraps JSON in markdown fences, and confirm long-term memory saves succeed without errors.
  • Unused import: Entity is imported but unused in test_converter_to_pydantic_strips_fences_multiline_no_function_calling.

Notes

Changed files

  • lib/crewai/src/crewai/utilities/converter.py (modified, +47/-5)
  • lib/crewai/tests/utilities/test_converter.py (modified, +160/-0)

PR #4528: Fix Pydantic validation error for LLM responses wrapped in markdown code blocks

Description (problem / solution / changelog)

Description

Fixes #4509 - Pydantic Validation error while saving in Memory

When LLMs return JSON responses wrapped in markdown code blocks (e.g., json...json...), the current Pydantic validation fails because it attempts to parse the entire response including markdown formatting as raw JSON.

This is a common issue where LLMs naturally format their JSON responses in markdown code blocks for readability, but the parsing logic expects raw JSON.

Root Cause

The Converter.to_pydantic() method was attempting to validate LLM responses directly with Pydantic without stripping markdown formatting. When LLMs returned responses like:

{
  "suggestions": ["Include more metrics", "Add visual charts"],
  "quality": 8.5,
  "entities": [...]
}

The parser would try to parse the entire string including ```json` markers, causing validation errors.

Solution

  • Added strip_markdown_code_blocks() function to extract raw JSON from markdown blocks
  • Updated Converter.to_pydantic() to strip markdown before validation attempts
  • Updated handle_partial_json() to clean markdown before pattern matching
  • Updated convert_to_model() to handle markdown-wrapped responses
  • Added comprehensive tests for markdown JSON parsing scenarios

Changes Made

  1. New function: strip_markdown_code_blocks(text: str) -> str

    • Extracts JSON from json...json... and ...json... blocks
    • Returns original text if no markdown blocks found
    • Handles both language-specified and plain code blocks
  2. Enhanced error handling in Converter.to_pydantic():

    • First attempts direct JSON validation
    • On ValidationError, strips markdown and retries
    • Falls back to existing partial JSON handling if still fails
  3. Updated helper functions:

    • handle_partial_json() now cleans markdown before pattern matching
    • convert_to_model() handles markdown-wrapped responses
  4. Comprehensive tests covering:

    • JSON with ```json` language specifier
    • JSON with plain ```` blocks
    • Regular JSON (unchanged behavior)
    • Edge cases and error scenarios

Testing

  • ✅ All new functionality tested with comprehensive test suite
  • ✅ Backward compatibility maintained (regular JSON unchanged)
  • ✅ Manual testing with reproduction case from issue #4509
  • ✅ Existing tests continue to pass

Impact

  • Fixes memory storage failures when LLMs wrap JSON in markdown
  • Improves reliability of TaskEvaluation parsing
  • Maintains backward compatibility for existing functionality
  • No breaking changes - only enhanced error handling

This fix resolves the core issue where CrewAI's memory system would fail when LLMs naturally format their JSON responses in markdown code blocks.

Changed files

  • lib/crewai/src/crewai/utilities/converter.py (modified, +55/-25)
  • lib/crewai/tests/utilities/test_converter.py (modified, +93/-0)

PR #4534: fix: strip markdown code blocks from LLM JSON responses in memory

Description (problem / solution / changelog)

Summary

Fixes #4509

When LLMs return JSON wrapped in markdown code blocks (```json ... ```), Pydantic validation fails with Invalid JSON error during memory storage. This is a common behavior across many LLM providers.

  • Added _strip_markdown_code_blocks() helper that removes triple-backtick wrappers before JSON parsing
  • Applied the helper at all JSON parsing entry points in converter.py: Converter.to_pydantic() (both function-calling and non-function-calling paths), convert_to_model(), and handle_partial_json()
  • Handles ```json, ```, and case-insensitive language tags

Test Plan

  • Added unit tests for _strip_markdown_code_blocks() (json blocks, plain blocks, no blocks, multiline, empty string, plain text)
  • Added integration tests for convert_to_model() with markdown-wrapped JSON
  • Added integration tests for Converter.to_pydantic() with both function-calling and non-function-calling LLMs
  • End-to-end test reproducing the exact TaskEvaluation scenario from #4509
  • Integration test for handle_partial_json() with markdown code blocks
  • All 11 new tests pass; all existing tests continue to pass

🤖 Generated with Claude Code

Changed files

  • lib/crewai/src/crewai/utilities/converter.py (modified, +32/-2)
  • lib/crewai/tests/utilities/test_converter.py (modified, +133/-0)

PR #4623: Fix Pydantic validation error when saving to memory

Description (problem / solution / changelog)

Summary

Fixes #4509

  • Strip markdown code fences (\``json ... ```) from LLM responses before JSON parsing in Converter.to_pydantic()andconvert_to_model()`
  • Some LLMs wrap JSON responses in markdown code blocks, causing ValidationError: Invalid JSON: expected value at line 1 column 1 during task evaluation memory saves
  • Reuses the same _CODE_BLOCK_PATTERN regex already established in base_converter_adapter.py for consistency

Test plan

  • Added 7 unit tests for _strip_markdown_code_fences() covering: json code fences, plain code fences, no code fences, multiline JSON, surrounding text, plain text passthrough, whitespace stripping
  • Added 4 integration tests for Converter.to_pydantic() and convert_to_model() verifying markdown-wrapped JSON is correctly parsed
  • Verified all existing converter and task evaluator tests still pass

🤖 Generated with Claude Code

Changed files

  • lib/crewai/src/crewai/utilities/converter.py (modified, +33/-0)
  • lib/crewai/tests/utilities/test_converter.py (modified, +111/-0)

PR #4627: fix: strip markdown code fences from LLM responses before JSON parsing

Description (problem / solution / changelog)

Summary

  • Fixes Pydantic ValidationError when LLM returns JSON wrapped in markdown code fences (e.g., ```json ... ```)
  • Adds _strip_code_fences() helper that extracts content from markdown code fence blocks before model_validate_json()
  • Applied to both function-calling and non-function-calling converter paths in Converter.to_pydantic()
  • This commonly occurs during memory saving when the LLM wraps TaskEvaluation JSON in code fences

Fixes #4509

Test plan

  • Verify JSON wrapped in ```json ... ``` is correctly parsed
  • Verify JSON wrapped in ``` ... ``` (no language tag) is correctly parsed
  • Verify plain JSON without fences still works correctly
  • Verify memory saving works when LLM returns code-fenced JSON

🤖 Generated with Claude Code

Changed files

  • lib/crewai/src/crewai/utilities/converter.py (modified, +23/-3)

Code Example

ERROR:root:OpenAI API call failed: 1 validation error for TaskEvaluation
  Invalid JSON: expected value at line 1 column 1 [type=json_invalid, input_value='

---



---

<img width="959" height="640" alt="Image" src="https://github.com/user-attachments/assets/14647808-9760-44bb-af9d-5eebcf9da4cb" />

### Steps to Reproduce

1. Run the POC code below.
2. Go through the console logs.
RAW_BUFFERClick to expand / collapse

Description

Getting the following Pydantic error while saving to memory.

ERROR:root:OpenAI API call failed: 1 validation error for TaskEvaluation
  Invalid JSON: expected value at line 1 column 1 [type=json_invalid, input_value='```json\n{\n  "assessmen...  ]\n    }\n  ]\n}\n```', input_type=str]
    For further information visit https://errors.pydantic.dev/2.11/v/json_invalid
[2026-02-18 18:17:49][ERROR]: Failed to add to long term memory: Failed to convert text into a Pydantic model due to validation error: 1 validation error for TaskEvaluation
  Invalid JSON: expected value at line 1 column 1 [type=json_invalid, input_value='```json\n{\n  "assessmen...  ]\n    }\n  ]\n}\n```', input_type=str]
    For further information visit https://errors.pydantic.dev/2.11/v/json_invalid
<img width="959" height="640" alt="Image" src="https://github.com/user-attachments/assets/14647808-9760-44bb-af9d-5eebcf9da4cb" />

Steps to Reproduce

  1. Run the POC code below.
  2. Go through the console logs.
from crewai import Agent, Task, Crew, Process
import os
from dotenv import load_dotenv

# Define agents
load_dotenv()
researcher = Agent(
    role="Senior Researcher",
    goal="Find comprehensive information on the given topic",
    backstory="You are an experienced researcher skilled at finding relevant information.",
    verbose=True,
)

writer = Agent(
    role="Report Writer",
    goal="Create a well-structured report based on research findings",
    backstory="You are a skilled writer who turns research into clear reports.",
    verbose=True,
)

# Define tasks
research_task = Task(
    description="Research the topic: {topic}",
    expected_output="A list of key findings about the topic.",
    agent=researcher,
)

writing_task = Task(
    description="Write a report based on the research findings.",
    expected_output="A comprehensive report in markdown format.",
    agent=writer,
    context=[research_task],
)

# Create crew with memory enabled and a custom embedding model
crew = Crew(
    agents=[researcher, writer],
    tasks=[research_task, writing_task],
    process=Process.sequential,
    memory=True,
    embedder={
        "provider": "openai",
        "config": {
            "model_name": "text-embedding-3-small",
            "api_key":os.getenv("API_KEY"),
            "api_base": os.getenv("BASE_URL")
        },
    },
    verbose=True,
)

# Kick off the crew
result = crew.kickoff(inputs={"topic": "AI in Healthcare"})
print(result.raw)

Expected behavior

CrewAI should successfully parse LLM output and save task evaluations to long-term memory without validation errors.

Screenshots/Code snippets

<img width="959" height="640" alt="Image" src="https://github.com/user-attachments/assets/04331f78-4331-422c-9dd6-8df4d86fcf2a" />

Operating System

macOS Sonoma

Python Version

3.10

crewAI Version

1.9.3

crewAI Tools Version

1.9.3

Virtual Environment

Venv

Evidence

.

Possible Solution

.

Additional context

I am already aware of the following issues, and I am on the latest version of CrewAI. It looks like this hasn’t been resolved yet:

https://github.com/crewAIInc/crewAI/issues/3915

extent analysis

Fix Plan

The fix involves modifying the crew initialization to properly handle JSON output from the OpenAI API.

  • Update the embedder configuration to include a response_parser that can handle the JSON output.
  • Ensure the api_key and api_base are correctly set in the environment variables.

Here's an example of the updated code:

crew = Crew(
    agents=[researcher, writer],
    tasks=[research_task, writing_task],
    process=Process.sequential,
    memory=True,
    embedder={
        "provider": "openai",
        "config": {
            "model_name": "text-embedding-3-small",
            "api_key": os.getenv("API_KEY"),
            "api_base": os.getenv("BASE_URL"),
            "response_parser": lambda x: x.json()  # Add this line
        },
    },
    verbose=True,
)

Alternatively, you can also try to parse the JSON output manually before passing it to the Crew initialization:

import json

# ...

response = crew.kickoff(inputs={"topic": "AI in Healthcare"})
try:
    json_output = json.loads(response.raw)
    # Process the json_output
except json.JSONDecodeError as e:
    print(f"Error parsing JSON: {e}")

Verification

To verify that the fix worked, run the updated code and check the console logs for any errors. The crew should now successfully parse the LLM output and save task evaluations to long-term memory without validation errors.

Extra Tips

  • Ensure that the API_KEY and BASE_URL environment variables are correctly set.
  • Check the OpenAI API documentation for any specific requirements or restrictions on the response_parser function.
  • If you're still experiencing issues, try printing out the response.raw output to see if it's in the expected JSON format.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

CrewAI should successfully parse LLM output and save task evaluations to long-term memory without validation errors.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING