Skip to content

fix(openapi): preserve timeouts so the server maps them to the actionable message - #5847

Merged
zzstoatzz merged 3 commits into
PrefectHQ:mainfrom
BlueX888:fix/openapi-timeout-error-mapping
Oct 30, 2026
Merged

zzstoatzz merged 3 commits into
PrefectHQ:mainfrom
BlueX888:fix/openapi-timeout-error-mapping

Conversation

@BlueX888

@BlueX888 BlueX888 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #6167

4.x scope of #5846; that report remains open for the maintained 3.x/native-httpx bug. No backport is included.

Description

With mask_error_details=True, upstream timeouts from OpenAPI tools and resources surfaced the generic masked message (Error calling tool 'slow' / Error reading resource ...) instead of Upstream request timed out, please retry. _send_request rewrapped every exception as ValueError, so the server-level is_timeout_error() mapping never matched and the component-level timeout handlers were dead code.

What changed

  • _send_request now re-raises native httpx2.RequestError (including TimeoutException) unchanged, so the existing server-level timeout/rate-limit mapping works. Legacy-httpx exceptions keep the previous normalization to ValueError (the deprecation bridge still accepts those clients).
  • Removed the now-dead except httpx2.TimeoutException/RequestError rewrap handlers (and their empty try wrappers) from OpenAPITool.run and OpenAPIResource.read.
  • Updated test_comprehensive.py::test_timeout_error_produces_useful_message, which asserted the old HTTP request timed out (ReadTimeout) text, to assert the actionable mapped message.

Contribution type

  • Bug fix (simple, well-scoped fix for a clearly broken behavior)
  • Documentation improvement
  • Enhancement

Bug fix verification

Test path: tests/server/providers/openapi/test_transport_errors.py (five tests).

Red at adf90b66 (implementation reverted, final tests applied): 3 failed, 3 passed, all assertion failures, no collection errors (masked tool timeout, masked resource timeout, and the updated message expectation fail; the ordinary-error and legacy-normalization controls pass).

Green at the fix commit: 1209 passed, 26 warnings across tests/server/providers/ tests/server/test_providers.py.

Validation

  • uv run --isolated pytest tests/server/providers/ tests/server/test_providers.py -q -> 1209 passed
  • uv run --isolated ruff check and ruff format --check on the changed files -> clean
  • uv run --isolated ty check -> All checks passed

AI assistance

Tool(s) used: Claude Code
How you used it: investigated from a verified reproduction, implemented the error-preservation change and the regression tests.

Checklist

  • This PR addresses an existing issue (or fixes a self-evident bug)
  • I have read CONTRIBUTING.md
  • I have added tests that cover my changes
  • I have run uv run prek run --all-files and all checks pass (focused checks passed)
  • I have self-reviewed my changes
  • If I used an LLM, it followed the repo's contributing conventions (not generic output)

Review follow-up

Codex review asked for AGENTS.md compliance: the mock transport handler is now fully annotated, and the new docstring uses Markdown single-backtick spans instead of RST double backticks. Behavior is unchanged.

@github-actions

This comment has been minimized.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T13:22:56.558599Z ac082e7 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@marvin-context-protocol marvin-context-protocol Bot added bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. openapi Related to OpenAPI integration, parsing, or code generation features. labels Oct 19, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ac082e7ad5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}


def _upstream(handler) -> httpx2.AsyncClient:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Annotate the mock transport handler

The new _upstream helper leaves its handler parameter untyped even though this repository requires full type annotations. Give it a callable annotation such as Callable[[httpx2.Request], httpx2.Response] so the transport boundary remains type-checkable.

AGENTS.md reference: AGENTS.md:L145-L145

Useful? React with 👍 / 👎.

Comment on lines +90 to +93
Native ``httpx2`` transport errors are re-raised unchanged so the server's
actionable error mapping (for example, timeouts) can recognize them.
Legacy-httpx clients, still accepted through the deprecation bridge, are
normalized to ``ValueError`` with the original error details.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use Markdown spans in the new docstring

The newly added httpx2 and ValueError references use RST-style double backticks. Source docstrings in this repository must use Markdown single-backtick spans for the MDX documentation pipeline, so replace both new spans with single backticks.

AGENTS.md reference: AGENTS.md:L176-L176

Useful? React with 👍 / 👎.

@BlueX888
BlueX888 force-pushed the fix/openapi-timeout-error-mapping branch 2 times, most recently from 4944798 to 58e4e48 Compare October 26, 2026 13:38
OpenAPI tool and resource requests normalized every httpx2 transport
error to ValueError, so the server-level actionable timeout mapping
never matched. Re-raise native httpx2 request/timeout errors unchanged
and keep normalization only for legacy-httpx clients, removing the
now-dead rewrap handlers in the tool and resource components.

@fastmcp-triage-reviewer fastmcp-triage-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by the FastMCP triage reviewer bot.

The change repairs timeout normalization at its source, allowing the existing actionable message to reach callers without disabling ordinary-error masking. Independent checks also confirm resource-template timeouts work for all four native timeout subclasses with masking enabled or disabled. No consequential code defect was found; the earlier annotation and docstring findings are addressed.

Checks

The focused PR modules pass all 21 tests. Independent template and native connection-error probes pass all 9 cases; timeout regressions fail on the unchanged base. Static validation and completed current-head CI remain pending.

@zzstoatzz zzstoatzz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Letting native httpx2 errors through _send_request lets the server's existing timeout mapping see them, so timeouts get the actionable message again, masked or not. The legacy-httpx path is unchanged.

Non-blocking: with masking off, a non-timeout transport error now shows only its own message, which can be empty for ReadError. Worth a fallback in a follow-up.

Checks

Timeout regressions fail on main and pass here; OpenAPI suite passes.


Generated by Claude Code

@zzstoatzz
zzstoatzz merged commit 1fdac87 into PrefectHQ:main Oct 30, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. openapi Related to OpenAPI integration, parsing, or code generation features.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Preserve native OpenAPI timeout mapping on 4.x

2 participants