Skip to content

fix(api-client): Use ApiClientError for non-JSON 400 responses - #1269

Merged
BYK merged 6 commits into
mainfrom
seer/fix/mcp-server-g2e
Oct 30, 2026
Merged

BYK merged 6 commits into
mainfrom
seer/fix/mcp-server-g2e

Conversation

@sentry

@sentry sentry Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Previously, SentryApiService.parseJsonResponse would throw a plain Error when it encountered a non-JSON response (e.g., HTML) for a 400 Bad Request. This plain Error was not recognized by isExpectedToolError as an expected API client error, causing it to be incorrectly logged as an unhandled exception in Sentry.

This change updates parseJsonResponse to use createApiError(...) instead of throw new Error(...) for both the HTML and generic non-JSON fallback paths. This ensures that these 400 responses are correctly classified as ApiClientError (specifically ApiValidationError), which isExpectedToolError will then suppress, preventing unnecessary Sentry alerts.

Fixes MCP-SERVER-G2E

Comment @sentry <feedback> on this PR to have Autofix iterate on the changes.

This PR was automatically generated by Sentry. You can adjust this setting at any time.

@sentry
sentry Bot marked this pull request as ready for review August 26, 2026 22:44
@sentry
sentry Bot requested a review from dcramer August 26, 2026 22:44
@github-actions github-actions Bot added the risk: low PR risk score: low label Sep 23, 2026

@sentry-junior sentry-junior 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.

The error factory correctly classifies the motivating non-JSON 400 from validateEvents while leaving unexpected successful HTML responses as reportable errors. Added MSW coverage for text/plain and text/html 400s plus a 200 HTML response, pushed as 27e4f15. All 98 API-client tests and the full tsc/lint/test gate pass locally. Awaiting current-head CI.

@sentry-junior sentry-junior 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.

Rechecked against the current failure and producer contract: the motivating issue still records parseJsonResponse throwing on HTTP 400 with no content type, and OrganizationEventsValidateEndpoint.get explicitly returns an empty 400 when its feature gate is unavailable. This is an expected API rejection, not evidence that successful non-JSON responses should be accepted; the error factory preserves that distinction.

Resolved the test-file conflict with main, preserving the single-tenant tests, and added the empty-body/no-content-type regression in 604c048. That regression fails with the original parser and passes with this fix. All 117 API-client tests plus build, typecheck, lint, and the full test suite pass locally. Current-head CI is still pending.

@github-actions github-actions Bot added risk: medium PR risk score: medium and removed risk: low PR risk score: low labels Sep 26, 2026

@sentry-junior sentry-junior 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.

Current-head verification is complete at 604c048. All 117 API-client tests pass locally again, and required test, smoke tests, typecheck/build gates, and code/security reviews have completed successfully. No actionable review threads remain.

The captured failure is a non-JSON HTTP 400 from validateEvents; the producer explicitly permits an empty feature-gate 400. The existing error factory correctly classifies that rejection while keeping successful HTML/non-JSON responses reportable as ApiError rather than ApiClientError. No additional corrections needed; the PR is non-draft and conflict-free.

Resolve the client.test.ts conflict by keeping both the validateEvents
non-JSON tests and main's bearer token validation tests.
# Conflicts:
#	packages/mcp-core/src/api-client/client.test.ts
@vercel

vercel Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
sentry-local Ready Ready Preview Oct 30, 2026 4:09pm UTC

Request Review

@sentry-junior sentry-junior 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.

Merged main again to clear the conflict with #1253, which added its validateEvents tests in the same spot in client.test.ts. I kept both test groups and both imports (ApiClientError and z). The parseJsonResponse fix is unchanged.

The fix is still needed. On main, both non-JSON fallbacks still throw a plain Error, so a 400 with an empty, text, or HTML body isn't treated as an expected client error. The new detail handling from #1253 only runs after JSON parsing succeeds, so it doesn't cover this path.

All 215 api-client tests and the full mcp-core suite pass, and tsc and oxlint are clean. If I put main's client.ts back, the three non-JSON 400 tests fail.

@github-actions github-actions Bot added risk: low PR risk score: low and removed risk: medium PR risk score: medium labels Oct 15, 2026
main moved response parsing into toolkit-core's readJsonResponse
(#1732, #1737), which still throws a plain Error for an empty or
non-JSON body. validateEvents is the only caller that lets a 400 reach
that parser, so classify its non-JSON 400s there with createApiError.
Successful non-JSON responses stay reportable.

@sentry-junior sentry-junior 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.

Merged main again to clear the conflict in client.ts (8d667ab). Since #1732 and #1737, SentryApiService.parseJsonResponse is gone. Responses are now parsed by toolkit-core's readJsonResponse, and it still throws a plain Error for an empty or non-JSON body. So the bug is still on main, just in a new place.

I took main's version of client.ts and moved the fix into validateEvents. That's the only caller that lets a 400 through to the parser (allowStatuses: [400]). The other allowStatuses callers allow only 404 on DELETE and never parse the body. A 400 without a JSON content type now becomes createApiError(..., 400), which is an ApiValidationError. JSON 400s with a detail envelope and malformed validation bodies are handled as before. Successful non-JSON responses are still reportable plain errors. I left the shared toolkit-core parser alone because the CLI maps its errors separately.

All 220 api-client tests and 1080 tools tests pass locally. mcp-core typecheck passes, and oxlint and oxfmt are clean. With main's client.ts put back, the 3 non-JSON 400 regression tests fail and the 200-HTML test still passes.

@github-actions github-actions Bot added risk: medium PR risk score: medium and removed risk: low PR risk score: low labels Oct 30, 2026
@BYK
BYK merged commit f7d17bd into main Oct 30, 2026
34 checks passed
@BYK
BYK deleted the seer/fix/mcp-server-g2e branch October 30, 2026 18:09

This branch was successfully deployed

1 active deployment
Preview — 8d667ab3 Deployed Oct 30, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: medium PR risk score: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant