How to Fix 'JSON parsing error when scaling' in CrewAI (Python)
What this error means
JSON parsing error when scaling in CrewAI usually means one of your agents or tools returned text that CrewAI expected to be valid JSON, but it got extra prose, malformed structure, or a type it couldn’t serialize. You typically see this when using structured outputs, tool calls, or when an agent is asked to return data that later gets parsed during task execution.
In practice, this shows up during crew.kickoff(), especially when a Task expects structured output or a tool returns a Python object instead of a JSON-safe string.
The Most Common Cause
The #1 cause is an agent returning non-JSON text when the task expects JSON, or a tool returning Python objects that are not serializable.
A common mistake is telling the model to “return JSON” without enforcing a schema, then parsing the result as if it were guaranteed valid.
| Broken pattern | Fixed pattern |
|---|---|
Free-form LLM output passed into json.loads() | Enforce structured output with a Pydantic model or strict prompt |
| Tool returns dict/object directly in a way CrewAI can’t serialize | Return a JSON string or use typed outputs |
# BROKEN
from crewai import Agent, Task, Crew
import json
researcher = Agent(
role="Researcher",
goal="Return customer risk summary as JSON",
backstory="You analyze insurance claims."
)
task = Task(
description="Summarize the claim and return JSON only.",
agent=researcher,
)
crew = Crew(agents=[researcher], tasks=[task])
result = crew.kickoff()
# This often fails because result is not strict JSON
data = json.loads(result.raw)
# FIXED
from pydantic import BaseModel
from crewai import Agent, Task, Crew
class ClaimSummary(BaseModel):
claim_id: str
risk_level: str
reasons: list[str]
researcher = Agent(
role="Researcher",
goal="Return customer risk summary in the exact schema.",
backstory="You analyze insurance claims.",
)
task = Task(
description=(
"Summarize the claim using only the required fields. "
"Do not add markdown or explanation."
),
agent=researcher,
expected_output=ClaimSummary.model_json_schema(),
)
crew = Crew(agents=[researcher], tasks=[task])
result = crew.kickoff()
If you’re using tools, make sure they return strings that can be parsed cleanly:
# BROKEN TOOL OUTPUT
def get_claim_data(claim_id: str):
return {"claim_id": claim_id, "amount": 12000} # may break downstream parsing
# FIXED TOOL OUTPUT
import json
def get_claim_data(claim_id: str):
return json.dumps({"claim_id": claim_id, "amount": 12000})
Other Possible Causes
1) The model wrapped JSON in markdown fences
CrewAI may receive something like:
{
"claim_id": "C-1001"
}
That looks fine to humans, but json.loads() will fail if the code fences are included in the raw output.
# BAD PROMPT
"Return JSON only in a markdown block."
# BETTER PROMPT
"Return raw JSON only. No markdown fences. No explanation."
2) A tool returned None or an unsupported type
If a tool returns None, bytes, datetime objects, or custom classes, serialization can fail during task scaling or handoff.
# BROKEN
from datetime import datetime
def audit_tool():
return {"checked_at": datetime.utcnow()} # not JSON serializable
# FIXED
from datetime import datetime
def audit_tool():
return {"checked_at": datetime.utcnow().isoformat()}
3) Nested quotes or trailing commas in generated JSON
LLMs often produce invalid JSON like trailing commas or unescaped quotes.
# BROKEN OUTPUT
{
"name": "ACME "Gold" Plan",
"status": "active",
}
# FIXED OUTPUT
{
"name": "ACME Gold Plan",
"status": "active"
}
If you need this reliably, don’t parse free-form text. Use schema validation after generation.
4) Version mismatch between CrewAI and dependencies
I’ve seen parsing issues caused by mismatched versions of crewai, pydantic, and provider SDKs. This is common after upgrading one package without pinning the rest.
crewai==0.x.x
pydantic==2.x.x
openai==1.x.x
Check for pinned versions and upgrade them together. If the issue started after an upgrade, roll back and test.
How to Debug It
- •
Inspect the raw output before parsing
- •Log
result.rawor the tool response exactly as returned. - •Look for markdown fences, extra commentary, trailing commas, or empty values.
- •Log
- •
Reduce the task to one agent and one tool
- •Remove delegation, memory, and multiple tools.
- •If the error disappears, one of those layers is producing invalid data during scaling.
- •
Validate against a schema immediately
- •Use Pydantic to catch bad output at the boundary.
- •Example:
from pydantic import BaseModel, ValidationError
class OutputSchema(BaseModel):
claim_id: str
status: str
try:
parsed = OutputSchema.model_validate_json(result.raw)
except ValidationError as e:
print(e)
- •Check whether the failure happens at kickoff or handoff
- •If it fails during
crew.kickoff(), inspect task outputs. - •If it fails during delegation/scaling across agents, inspect intermediate outputs from each agent and each tool call.
- •If it fails during
Prevention
- •
Use typed outputs everywhere
- •Prefer Pydantic models over “JSON-only” prompts.
- •Validate at every boundary between agent output and Python code.
- •
Keep tool outputs JSON-safe
- •Return strings, numbers, booleans, lists, and dicts with primitive values only.
- •Convert datetimes with
.isoformat()and avoid custom objects.
- •
Pin your dependency versions
- •Lock
crewai,pydantic, and provider SDKs together. - •Re-test after upgrades before deploying to production workflows.
- •Lock
If you’re seeing JSON parsing error when scaling in CrewAI Python code, start with the raw output first. In most cases, the bug is not “CrewAI scaling” itself — it’s invalid structured data slipping through an agent or tool boundary.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit