diff --git a/packages/core/src/utils/node-stack-trace.ts b/packages/core/src/utils/node-stack-trace.ts index 1132471b0e8f..1dfe24e9f783 100644 --- a/packages/core/src/utils/node-stack-trace.ts +++ b/packages/core/src/utils/node-stack-trace.ts @@ -115,9 +115,10 @@ export function node(getModule?: GetModuleFn): StackLineParserFn { filename = lineMatch[5]; } + const maybeDecodedFilename = filename ? _safeDecodeURI(filename) : undefined; return { - filename: filename ? decodeURI(filename) : undefined, - module: getModule ? getModule(filename) : undefined, + filename: maybeDecodedFilename ?? filename, + module: maybeDecodedFilename && getModule?.(maybeDecodedFilename), function: functionName, lineno: _parseIntOrUndefined(lineMatch[3]), colno: _parseIntOrUndefined(lineMatch[4]), @@ -148,3 +149,11 @@ export function nodeStackLineParser(getModule?: GetModuleFn): StackLineParser { function _parseIntOrUndefined(input: string | undefined): number | undefined { return parseInt(input || '', 10) || undefined; } + +function _safeDecodeURI(filename: string): string | undefined { + try { + return decodeURI(filename); + } catch { + return undefined; + } +} diff --git a/packages/core/test/lib/utils/stacktrace.test.ts b/packages/core/test/lib/utils/stacktrace.test.ts index 0551a74be6f0..49ea7fcc0ba5 100644 --- a/packages/core/test/lib/utils/stacktrace.test.ts +++ b/packages/core/test/lib/utils/stacktrace.test.ts @@ -392,4 +392,21 @@ describe('node', () => { expect(node(input)).toEqual(expectedOutput); }); + + it('returns the raw filename when decodeURI throws a URIError', () => { + const malformedFilename = '/path/to/%file%.js'; + const input = `at myFunction (${malformedFilename}:10:5)`; + + const result = node(input); + + expect(result?.filename).toBe('/path/to/%file%.js'); + }); + + it('decodes a valid percent-encoded filename', () => { + const input = 'at myFunction (/path/to/my%20file.js:10:5)'; + + const result = node(input); + + expect(result?.filename).toBe('/path/to/my file.js'); + }); });