Skip to content

fix(mcp): List existing attributes when search validation rejects a key - #2211

Draft
sentry-junior[bot] wants to merge 1 commit into
mainfrom
fix/mcp-unknown-attribute-suggestions
Draft

sentry-junior[bot] wants to merge 1 commit into
mainfrom
fix/mcp-unknown-attribute-suggestions

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

When a caller passes explicit fields to search_logs / search_traces / search_metrics, the handler trusts them over the embedded agent's picks. If one is wrong, the final validation gate fails with only Sentry's Unknown attribute, so the caller has no way to find the right key.

On that failure, the handler now looks up attributes that share the rejected key's stem (error.message → error). It uses the same dataset, project, and time range, does at most 3 lookups and lists up to 10 keys each, then adds them to the error:

Search validation failed:
Validation Result: invalid
Validated Fields:
- INVALID error.message — Unknown attribute
- INVALID error.stack — Unknown attribute

Attributes that exist on logs in this time range:
- matching `error`: `error`, `error.type`
Use one of these keys, or drop the unknown field.

If the lookup fails, the hint is skipped (we log a warning) and the original validation error stays unchanged.

Why: user feedback MCP-SERVER-GPC (opencode, 0.42.0). In span bc2a4ee252160576 (trace c3c0ff03…), search_logs was called with fields: [..., "error", "error.message", "error.stack"]. The final /events/validate/ returned Unknown attribute for both keys (sentry organization_events_validate.py:318), and the tool answered with only that. The embedded agent had already looked these keys up via datasetAttributes, but because explicit fields are trusted (resolveEventFields, search.ts), its picks were dropped. The retry without the two fields worked; the real key was error.

Not covered: the same feedback also said search_issues rewrote "organization step(s) failed" to organization step failed. That call isn't in the sampled spans, so it isn't fixed here. It's tracked separately.

Tests: regression test in search-events.test.ts (fails without this change), plus a test that a failing lookup keeps the original error. mcp-core tsc, oxlint, oxfmt and the full mcp-core vitest suite pass locally.

via Sentry.

--

View Session [Sentry]

Sentry's events/validate endpoint only says "Unknown attribute" for a
key it can't resolve. When a caller passes explicit fields to search_logs,
search_traces, or search_metrics, the handler trusts them and the final
validation gate fails with no way to find the right key.

On that failure, look up attributes that share the rejected key's stem
(error.message -> error) in the same dataset, project, and time range, and
append them to the error. A failed lookup leaves the error unchanged.

Fixes MCP-SERVER-GPC (search_logs rejected error.message and error.stack;
the real key was error).
@vercel

vercel Bot commented Nov 12, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated
sentry-local Skipped Skipped Nov 12, 2026 7:34pm UTC

Request Review

@sentry-junior

sentry-junior Bot commented Nov 15, 2026

Copy link
Copy Markdown
Contributor Author

Another report of this pattern, from search_logs (MCP user feedback MCP-SERVER-GQC, server 0.42.0). Reports: 2 (GPC and this one).

Evidence (log 01a1dd99dc2f7a758455f6662cf9a94b, trace a5d135efde0b465b863ec38d06414106, search_logs query failed, UserInputError):

  • query: environment:production timestamp:>=<ISO> message:"Job completed". This is pure syntax, so it ran without the agent.
  • error: Search validation failed: … INVALID server_name — Unknown attribute, from the /events/validate/ gate (search.ts:1232 on main @ d9c69544; Sentry organization_events_validate.py:318).
  • The retry 16s later (trace 551bf64422774176be1a984399cc2c4f) used the same query with fields: ["timestamp","message","trace"] and succeeded. So server_name came from the caller's explicit fields. The failing call's span wasn't sampled, so I'm inferring the full original fields list.

Gap in this PR for this case: attributeStem only splits on ., so server_name stays server_name. The substring lookup would most likely print matching server_name: none. That at least tells the caller the key is missing, but it won't point to the log-side key. server_name is an errors-dataset field, and the closest log attribute is probably server.address, which is an inference I haven't checked against this project's attributes. You could also split the stem on _, or map known errors-only fields to their log or span equivalents.

This branch was successfully deployed

1 active and 1 inactive deployments
Actions — 394c8bcd Deployed Nov 12, 2026 by sentry-junior[bot] via eval #1821
Preview — 394c8bcd Deployed Nov 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants