Resolved

TypeError: CallToolResult is not iterable in FastMCP migration

Python
API
Migration
Debugging
Error Handling
FastMCP
TypeError

FastMCP 2.0 introduced a breaking change where the `call_tool()` function returns a `CallToolResult` object instead of a plain dictionary, causing `TypeError` when using legacy dictionary access patterns.

A video generation orchestrator relying on FastMCP encountered a breaking change in version 2.0. Previously, the call_tool() function returned a plain dictionary, but the updated version now returns a structured CallToolResult object. This change caused a TypeError when the system attempted to use dictionary-style access (e.g., if "error" in result) on the new object type, affecting error handling and data extraction across multiple locations.

Issue

The orchestrator fails with TypeError: 'CallToolResult' is not iterable when it tries to access the result of call_tool() as a dictionary. The system expects a plain dictionary but receives a CallToolResult object, breaking existing error-handling and data-extraction logic.

Culprit

FastMCP 2.0 introduced a structured object (CallToolResult) to replace the previous plain dictionary return type. Key changes include:

  • Structured data access: Data is now accessed via properties (e.g., .data) instead of direct dictionary keys.
  • Error handling: Errors are now raised as exceptions rather than returned as part of the result object.
  • Content access: Raw content blocks are stored in a .content property.

The existing codebase relied on legacy patterns like result["key"] and if "error" in result, which are incompatible with the new object structure.

Solution

Updated Error Handling

Replace dictionary-based error checks with structured exception handling:

  • Use try/except blocks to catch exceptions raised by the call_tool() function.
  • Access structured data via properties (e.g., .data) instead of direct dictionary access.

Data Extraction Refactoring

Modify all return paths to extract data from the .data property of the CallToolResult object before further processing.

Backward Compatibility

Maintain compatibility with the previous data structure by leveraging the .data property, which mirrors the structure of the legacy dictionary.

Key Changes Made:

  1. Replaced all dictionary-style access (result["key"]) with property-based access (result.data["key"]).
  2. Converted error-checking logic (e.g., if "error" in result) to exception handling.
  3. Updated all relevant locations in the orchestrator to handle the new object structure.
  4. Ensured backward compatibility with legacy data formats where applicable.