From b7ad186e86f3afb62b3abeacf5c6055e077d9018 Mon Sep 17 00:00:00 2001 From: Geezy Date: Wed, 4 Nov 2026 09:25:03 +0100 Subject: [PATCH] fix(client-runtime): sanitized error stacks keep line and column for URLs with a query The stack sanitizer matches a frame's URL together with its trailing :line:column. When the URL has a query string or fragment, URL parsing puts that position inside the search or hash, and clearing them dropped it. Frames from Vite dev modules (?v=, ?t=) and Metro bundles lost every position. Keep a trailing :line[:column] from the removed query or fragment and append it to the sanitized URL. Credentials, query and fragment are still removed. Co-Authored-By: Claude Opus 5.5 --- packages/client-runtime/src/errors/safeLog.test.ts | 8 +++++++- packages/client-runtime/src/errors/safeLog.ts | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/client-runtime/src/errors/safeLog.test.ts b/packages/client-runtime/src/errors/safeLog.test.ts index c696b5f4431ff..1e4fc4a993c5d 100644 --- a/packages/client-runtime/src/errors/safeLog.test.ts +++ b/packages/client-runtime/src/errors/safeLog.test.ts @@ -13,6 +13,8 @@ describe("safeErrorLogAttributes", () => { error.stack = [ "ProjectRemovalError: outer-error-secret-sentinel", " at removeProject (https://user:password@example.com/project.ts?token=secret#fragment)", + " at loadSettings (http://localhost:5173/src/useSettings.ts?t=1730700000000:162:7)", + "removeAll@https://example.com/app.js?token=secret:12:5", ].join("\n"); const attributes = safeErrorLogAttributes(error); @@ -22,7 +24,11 @@ describe("safeErrorLogAttributes", () => { errorName: "Error", errorTag: "ProjectRemovalError", traceId: "trace-safe-123", - stack: " at removeProject (https://example.com/project.ts)", + stack: [ + " at removeProject (https://example.com/project.ts)", + " at loadSettings (http://localhost:5173/src/useSettings.ts:162:7)", + "removeAll@https://example.com/app.js:12:5", + ].join("\n"), }); const diagnosticText = Object.values(attributes).map(String).join("\n"); expect(diagnosticText).not.toContain("outer-error-secret-sentinel"); diff --git a/packages/client-runtime/src/errors/safeLog.ts b/packages/client-runtime/src/errors/safeLog.ts index 60730d4d35cc6..2f2015b30bfca 100644 --- a/packages/client-runtime/src/errors/safeLog.ts +++ b/packages/client-runtime/src/errors/safeLog.ts @@ -18,11 +18,13 @@ function readSafeLabel(value: unknown): string | undefined { function sanitizeStackUrl(value: string): string { try { const url = new URL(value); + // A frame's trailing :line:column parses as part of the query or fragment when one is present. + const position = /(?::\d+){1,2}$/.exec(url.hash || url.search)?.[0] ?? ""; url.username = ""; url.password = ""; url.search = ""; url.hash = ""; - return url.toString(); + return url.toString() + position; } catch { return value; }