Skip to content

fix(mcp-core): Allow string 'count' in EventsStatsResponseSchema - #1424

Open
sentry[bot] wants to merge 3 commits into
mainfrom
seer/fix/mcp-events-stats-count-type
Open

sentry[bot] wants to merge 3 commits into
mainfrom
seer/fix/mcp-events-stats-count-type

Conversation

@sentry

@sentry sentry Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

This PR addresses a ZodError occurring when the Sentry /events-stats/ API returns the count field as a string, particularly for non-additive aggregates like max(timestamp).

Root Cause:
The EventsStatsResponseSchema in packages/mcp-core/src/api-client/schema.ts was expecting count to always be a number (z.number()), but the Sentry API can return it as a string (e.g., an epoch timestamp string or an ISO datetime string).

Changes Made:

  1. Schema Update: Modified EventsStatsResponseSchema in packages/mcp-core/src/api-client/schema.ts to define the count field as z.union([z.string(), z.number()]). This allows the schema to correctly parse both numeric and string representations of count.
  2. Formatter Logic Refinement: Updated the formatTimeSeriesResults function in packages/mcp-core/src/tools/support/search-events/formatters.ts.
    • The value used for calculations (e.g., total, peak comparison) is now derived by coercing the raw count to a number using Number(). If coercion results in NaN (e.g., for ISO datetime strings), value defaults to 0 for arithmetic safety.
    • A new display property was introduced for each data point. This property holds the raw string value if it's not a valid number, or the localized numeric string otherwise. This ensures that non-numeric values (like ISO datetimes) are displayed correctly to the user instead of NaN.
    • All output formatting (peak, table rows) now uses this display property.
  3. Regression Test: Added a new test case in packages/mcp-core/src/tools/catalog/search-events.test.ts to specifically cover the scenario where the API returns ISO datetime strings for count. This test asserts that the output correctly includes the datetime string and does not contain NaN.

These changes ensure robust handling of varying count data types from the Sentry API, preventing validation errors and improving the display of time series results.

Fixes MCP-SERVER-GCQ

@sentry <feedback>: Autofix iterates on these changes
@sentry stop iterating: Autofix stops iterating on this run

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

@sentry
sentry Bot deployed to Actions October 6, 2026 10:49 Active
@github-actions github-actions Bot added the risk: low PR risk score: low label Oct 6, 2026

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d6bfafc. Configure here.

Comment thread packages/mcp-core/src/tools/support/search-events/formatters.ts Outdated
@sentry
sentry Bot deployed to Actions October 6, 2026 11:07 Active
@github-actions github-actions Bot added risk: medium PR risk score: medium and removed risk: low PR risk score: low labels Oct 6, 2026
Date-typed aggregates such as max(timestamp) return ISO datetime strings
from events-stats, while empty buckets are zero-filled with 0. Coercing
the strings to 0 made Peak report an empty bucket. Order them by parsed
time instead, and cover the zero-filled production shape.

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

I checked the motivating failure and the change is justified. I pushed one correction in 6ede0d4.

Evidence: The only MCP-SERVER-GCQ event came from search_events on the errors dataset. It requested events-stats with yAxis=max(timestamp), and the ZodError reports expected number, received string only for buckets that had data (indices 6–12 and 22–24). That matches Sentry's producer: SnubaTSResultSerializer emits {"count": r.get(column, 0)} without type coercion, and zerofill writes a numeric 0 into empty buckets. So for date-typed aggregates, count is legitimately a datetime string next to numeric zeros. Widening the schema to string | number is the right-sized fix. The response is still validated as a tuple of buckets.

Correction: The formatter coerced datetime strings to 0. With the real response shape, every value was 0, so Peak pointed at the first empty bucket (Peak: 0 at …), not the latest timestamp. Datetime strings are now ordered by Date.parse and still displayed as the raw string. Numeric and additive handling is unchanged. I also updated the ISO test to include a zero-filled bucket and +00:00 offsets, and to assert the peak. Without the formatter change, that test fails with Peak: 0. I also applied oxfmt to the schema line.

Verification: mcp-core typecheck passes, and so does the full mcp-core test suite (1755 passed, 6 skipped). Repo lint passes and the touched files pass the oxfmt check. Reverting the schema change makes both new tests fail.

This branch was successfully deployed

1 active deployment
Actions — 6ede0d45 Deployed Oct 6, 2026 by sentry-junior[bot] via eval #1247
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.

0 participants