Add @handle_tool_errors decorator for standardized error handling (#2885)

* Add @handle_tool_errors decorator for standardized error handling

* Add tests for @handle_tool_errors decorator

* Add documentation for @handle_tool_errors decorator

* Fix type checking: use getattr for func.__name__ with fallback

* Add @overload declarations for proper async/sync type checking

* Fix type checking: reorder overloads and use Coroutine for async typing

* Update lockfile and fix test formatting

* Improve error_handling module: add docstrings, fix logging, handle cancellation, and update documentation

* Add auth error mappings, doc tweaks, and doc fix

* Pivot to hybrid approach

* Remove decorator, keep only core 429/timeout handling

---------

Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
This commit is contained in:
Diogo Santos 2026-02-04 23:30:31 +00:00 committed by GitHub
commit b776089ecc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1095,6 +1095,18 @@ class FastMCP(
raise
except Exception as e:
logger.exception(f"Error calling tool {name!r}")
# Handle actionable errors that should reach the LLM
# even when masking is enabled
if isinstance(e, httpx.HTTPStatusError):
if e.response.status_code == 429:
raise ToolError(
"Rate limited by upstream API, please retry later"
) from e
if isinstance(e, httpx.TimeoutException):
raise ToolError(
"Upstream request timed out, please retry"
) from e
# Standard masking logic
if self._mask_error_details:
raise ToolError(f"Error calling tool {name!r}") from e
raise ToolError(f"Error calling tool {name!r}: {e}") from e
@ -1198,6 +1210,17 @@ class FastMCP(
raise
except Exception as e:
logger.exception(f"Error reading resource {uri!r}")
# Handle actionable errors that should reach the LLM
if isinstance(e, httpx.HTTPStatusError):
if e.response.status_code == 429:
raise ResourceError(
"Rate limited by upstream API, please retry later"
) from e
if isinstance(e, httpx.TimeoutException):
raise ResourceError(
"Upstream request timed out, please retry"
) from e
# Standard masking logic
if self._mask_error_details:
raise ResourceError(
f"Error reading resource {uri!r}"
@ -1226,6 +1249,17 @@ class FastMCP(
raise
except Exception as e:
logger.exception(f"Error reading resource {uri!r}")
# Handle actionable errors that should reach the LLM
if isinstance(e, httpx.HTTPStatusError):
if e.response.status_code == 429:
raise ResourceError(
"Rate limited by upstream API, please retry later"
) from e
if isinstance(e, httpx.TimeoutException):
raise ResourceError(
"Upstream request timed out, please retry"
) from e
# Standard masking logic
if self._mask_error_details:
raise ResourceError(f"Error reading resource {uri!r}") from e
raise ResourceError(f"Error reading resource {uri!r}: {e}") from e