From e8239af2cb2b4a145651b9ee6d30c267dc4ffe44 Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2026 09:40:43 +0000 Subject: [PATCH] fix(solidstart): Read server action route from the request's root span Since Nitro's h3 route handler opens a `handler` span instead of a nested `http.server` span (#25295), the active span during a server function call has no `url.path`, so `withServerActionInstrumentation` no longer recognized `/_server` requests and stopped renaming the segment to the server action name. Co-Authored-By: Francesco Gringl-Novy --- .../server/withServerActionInstrumentation.ts | 6 +++-- .../withServerActionInstrumentation.test.ts | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/solidstart/src/server/withServerActionInstrumentation.ts b/packages/solidstart/src/server/withServerActionInstrumentation.ts index 785ab1432f91..68d4ff5221c7 100644 --- a/packages/solidstart/src/server/withServerActionInstrumentation.ts +++ b/packages/solidstart/src/server/withServerActionInstrumentation.ts @@ -1,6 +1,6 @@ import { handleCallbackErrors, SPAN_STATUS_ERROR } from '@sentry/core'; import { flushIfServerless } from '@sentry/core/server'; -import { captureException, getActiveSpan, spanToJSON, startSpan } from '@sentry/node'; +import { captureException, getActiveSpan, getRootSpan, spanToJSON, startSpan } from '@sentry/node'; import { isRedirect } from './utils'; import { SENTRY_SEGMENT_NAME_SOURCE, @@ -25,7 +25,9 @@ export async function withServerActionInstrumentation { expect(mockSpanSetAttribute).to.toHaveBeenCalledWith(SENTRY_SEGMENT_NAME_SOURCE, 'route'); }); + it('sets a server action name on the root span when the active span is a nested handler span', async () => { + const rootSpan = new SentryCore.SentrySpan({ + attributes: { + 'url.path': '/_server', + [SENTRY_OP]: 'http.server', + }, + }); + const handlerSpan = new SentryCore.SentrySpan({ + attributes: { + [SENTRY_OP]: 'handler', + }, + }); + SentryCore.addChildSpanToSpan(rootSpan, handlerSpan); + mockGetActiveSpan.mockReturnValue(handlerSpan); + const mockRootSpanSetAttribute = vi.spyOn(rootSpan, 'setAttribute'); + + await serverActionGetPrefecture(); + + expect(mockRootSpanSetAttribute).toHaveBeenCalledWith('http.route', 'getPrefecture'); + expect(mockRootSpanSetAttribute).toHaveBeenCalledWith(SENTRY_SEGMENT_NAME_SOURCE, 'route'); + }); + it('does not set a server action name if the active span had a non `/_server` `url.path`', async () => { const span = new SentryCore.SentrySpan(); span.setAttribute('url.path', '/users/5');