bun
bun copied to clipboard
Sourcemaps ignored by apps bundled with `Bun.build` and `sourcemap: 'external'`
What version of Bun is running?
1.1.9+bb13798d9
What platform is your computer?
Darwin 23.4.0 arm64 arm
What steps can reproduce the bug?
- Bundle app using
Bun.build
and the following build configuration:
{
define: {},
entrypoints: ['./src/index.mts'],
external: [],
format: 'esm',
loader: {},
minify: true,
naming: {
chunk: '[name].[hash].mjs',
entry: '[name].mjs',
},
outdir: './dist',
plugins: [],
publicPath: '',
root: '.',
sourcemap: 'external',
splitting: true,
target: 'bun',
}
- Start app using the bundled resources
- Make the app throw an error
- Get a minified stack trace instead of a link back to the original source code
What is the expected behavior?
If I run the same code with a manually thrown error but point to the typescript files directly instead of using pre-bundled ones, I get the following stack trace:
30 |
31 | // Lambda Handler
32 | async function lambdaHandler(request: Request): Promise<Response> {
33 | customizeRollbarPayload(request);
34 |
35 | throw new Error('boooo');
^
error: boooo
at /Users/egoldstein/code/babbel/get.apigateway.lambda/src/index.mts:35:9
at lambdaHandler (/Users/egoldstein/code/babbel/get.apigateway.lambda/src/index.mts:32:30)
at /Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/networkUtils.mts:201:20
at /Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/networkUtils.mts:190:48
at /Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/timeUtils.mts:100:29
at measureElapsedTime (/Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/timeUtils.mts:98:38)
at /Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/networkUtils.mts:190:17
at fetch (/Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/networkUtils.mts:186
The bundled app stack trace should look the same.
What do you see instead?
1 | // @bun
2 | import{d as j} from"./index.8b306d478767a477.mjs";import"./index.04c119a3beb16a35.mjs";import{m as W,q as F,r as K,t as _} from"./index.cc647d1f6d9b8e22.mjs";var{dns:x}=globalThis.Bun;var{Glob:w}=globalThis.Bun;var A=["ALL","DELETE","GET","HEAD","OPTIONS","PATCH","POST","PUT"];class B{constructor(Q=!0){this.#Y=[],this.#Z=Q}#Y;#Z;async handleRequest(Q){const Y=performance.now(),{method:Z}=Q,{pathname:$}=new URL(Q.url);for(let[X,[O,z]]of this.#Y){if(X!=="ALL"&&Z!==X)continue;if(new w(O).match($)){if(typeof z==="function"){if(this.#Z)Q.headers.append(...j("routeSync",Y));return z(Q)}const[D]=Object.entries(z);if(!D)throw new TypeError("No lazy-loaded configuration option provided");const[G,k]=D,C=(await k())[G];if(typeof C==="function"){if(this.#Z)Q.headers.append(...j("routeAsync",Y));return C(Q)}throw new TypeError(`Lazy-loaded route handler target "${G}" was not a function`)}}throw new Error("No routes matched!")}#Q(Q,Y,Z){if(!A.includes(Z))throw new TypeError(`"${Z}" is not a valid HTTP method`);return this. | ... truncated
error: boooo
at /Users/egoldstein/code/babbel/get.apigateway.lambda/dist/index.mjs:2:7221
at f (/Users/egoldstein/code/babbel/get.apigateway.lambda/dist/index.mjs:2:7512)
at /Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/networkUtils.mts:201:20
at /Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/networkUtils.mts:190:48
at /Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/timeUtils.mts:100:29
at measureElapsedTime (/Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/timeUtils.mts:98:38)
at /Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/networkUtils.mts:190:17
at fetch (/Users/egoldstein/code/babbel/get.apigateway.lambda/node_modules/@mangs/bun-utils/src/networkUtils.mts:186
Additional information
I've been working through this with @paperdave and we've tracked this down to potentially being caused by a null byte being inserted into .map
file(s). Could be more than that, but that's where we've gotten so far.
I used the esbuild sourcemap visualizer to figure that out. Thanks Dave for the suggestion.
The visualizer gives the following error when trying to examine the entrypoint code and its sourcemap:
The imported source map contains invalid JSON data: JSON.parse: bad control character in string literal at line 11 column 28 of the JSON data
The null byte at line 11 column 28 from the source map file looks like this in VSCode: