bundler: log the resolve error for an entry point too long for a path buffer - #38391
bundler: log the resolve error for an entry point too long for a path buffer#38391robobun wants to merge 1 commit into
Conversation
… buffer resolve_entry_point's callers rely on it logging the error before returning it. The arm that skips the directory-cache bust for an entry point whose path cannot fit a PathBuffer returned without logging, so the entry point was silently dropped: Bun.build succeeded without it when another entry point was given and hit the linker's no-chunks assertion when it was the only one, and a Worker given such a path reported "BuildMessage: undefined". Skip only the cache bust for those paths and fall through to the logging.
|
Warning Review limit reached
Next review available in: 20 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
Comment |
There was a problem hiding this comment.
LGTM — the length guard now falls through to the existing error-logging path instead of returning ahead of it, so an over-long entry point is reported like any other unresolved one.
What was reviewed:
resolve_entry_pointcontrol flow:break 'name falseskips only the cache-bust/retry (which needs thePathBuffer), then reacheslog_mut().add_error_fmt(...); entry points that fit take the identical path as before.- Confirmed callers (
enqueue_entry_points_normal, the Worker resolve path) rely on the log entry rather than theErr— the doc comment on this function says as much, and the fix is at the right layer. - Both new tests spawn a child / await the event, assert exact messages, cover the alone + alongside-valid-entry cases and the Worker face, and follow harness conventions (
Buffer.alloc,tempDir, concurrent pipe drain, exit-code last).
Extended reasoning...
Overview
The PR relocates an existing length guard in Transpiler::resolve_entry_point (src/bundler/transpiler.rs). Previously the guard was a separate Err(err) if <too long> => Err(err) match arm ahead of the arm that busts the directory cache, retries, and — crucially — logs the error. That arm returned Err without logging, so callers that consume the log (enqueue_entry_points_normal just continues on Err; the Worker turns the log into the error event's message) saw nothing: a build with zero entry points panicked in the linker, a build with a valid sibling silently succeeded, and a Worker fired BuildMessage: undefined.
The fix moves the same predicate inside the 'name labelled block as break 'name false, so the cache-bust step (the only part that needs the fixed-size PathBuffer) is skipped and control falls through to self.log_mut().add_error_fmt(...). The error is now logged with the same format as every other unresolved entry point. No behavior change for entry points that fit the buffer.
Two tests are added: one in bun-build-api.test.ts that spawns a child bun and asserts a 100 000-byte entry point produces exactly one ModuleNotFound BuildMessage and zero outputs, both alone and alongside a valid entry point; and one in worker.test.ts that asserts new Worker(longSpecifier) fires an error event whose message names the specifier. Both follow the repo's harness conventions (tempDir, bunEnv, Buffer.alloc(n, fill), concurrent stdout/stderr/exit drain, exit code asserted last, child process so a crash surfaces as a failed assertion).
Security risks
None. This is error-message plumbing on an already-failing resolve path; no new parsing, no allocation sized by the input, no privilege or filesystem effects. The over-long path never reaches join_abs_string_buf_z (unchanged from before — the guard predicate is the same), so the PathBuffer unchecked-write concern is unaffected.
Level of scrutiny
Low. The Rust change is an 8-line relocation of an existing condition within one function, changing which arm falls through to already-existing logging code. The function's own doc comment states it reports the error to the log; the fix makes the too-long branch honor that contract. The tests are additive and placed in the existing files for their modules.
Other factors
The PR description documents USE_SYSTEM_BUN=1 failing both new tests with the exact symptoms described (panic / success: true / BuildMessage: undefined) and bun bd test passing, plus that the full bun-build-api.test.ts and plugins.test.ts still pass. It explicitly scopes out the adjacent within-a-few-bytes resolver write (#35857). No prior human reviews or outstanding comments on the timeline (only a CodeRabbit rate-limit notice).
|
Status: nothing outstanding from review; the change is the 8-line relocation of the length guard described above plus the two tests, both verified failing on the released build and passing here. Sibling PRs from the same census: #38379 (shell mkdir/touch) and #38392 (_nodeModulePaths, onResolve paths); all three are independent. Waiting on CI. |
|
Updated 4:05 AM PT - Aug 14th, 2026
❌ @robobun, your commit f78f612 has some failures in 🧪 To try this PR locally: bunx bun-pr 38391That installs a local version of the PR into your bun-38391 --bun |
|
Ready for a maintainer. The change is unchanged since it was opened (head f78f612): the length guard in resolve_entry_point now only skips the cache bust, so the error is logged like any other; the Bun.build test and the Worker test both fail on the released build and pass here, and both passed on every lane of build 95583. The lanes that build reports as failed are retry-passed flakes in unrelated files (fs read-stream pos, inspect-error-leak, bun-patch and filter-workspace on Windows aarch64, a napi threadsafe-function batch, cluster-shared-leak, malformed-integrity-base64), so I am not pushing a retrigger for them. Sibling PRs from the same census: #38379, #38392. |
…-no-bundle entries resolve_entry_point is back to what main has: #38391 already carries the same change with tests that also cover Windows and Bun.build. The browser field message gets the same "(entry point)" suffix #38778 uses, and the new test pins that --no-bundle now resolves "entry" to entry.ts the way a bundling build does.
Problem
Bun.build({ entrypoints: [name] })wherecwd/namedoes not fit a path buffer (4096 bytes on Linux, 1024 on macOS) aborts the process instead of failing the build:panic: index out of bounds: the len is 0 but the index is 0(release) /assertion failed: chunks.len() > 0ingenerateChunksInParallel.rs(debug).Bun.build({ entrypoints: ["./valid.js", name] })instead succeeds: one output, no logs, the long entry point silently dropped.new Worker(name)with such a path fires its error event withBuildMessage: undefined(the "Worker prints error: undefined" face from the path-length census).Transpiler::resolve_entry_point(src/bundler/transpiler.rs) is documented as logging the resolve error before returning it, and all of its callers rely on that (enqueue_entry_points_normalinbundle_v2.rsjustcontinues onErr; the Worker code turns the log into the event's message). The guard added for paths too long to build the cache-buster name in aPathBufferreturnedErrfrom a match arm ahead of the logging, so for those paths nothing was logged: the bundle went on with zero entry points, and the Worker converted an empty log.Fix
ModuleNotFound resolving "<name>" (entry point). Entry points that fit take the same path as before.test/bundler/bun-build-api.test.ts, "an entry point too long for a path buffer is reported like any other missing one": a child bun builds a 100000-byte entry point (longer than the buffer on Windows too) alone and next to a valid one; both must fail with that one message and no outputs.test/js/web/workers/worker.test.ts, "names the entry point when its path is too long for a path buffer": the error event's message must name the entry point.USE_SYSTEM_BUN=1: the build test fails (child aborts with the panic above; the two-entry-point case on its own reportssuccess: true, 1 output), the worker test fails withReceived: "BuildMessage: undefined".bun bd teston this branch: both pass; the fullbun-build-api.test.tsandplugins.test.tsfiles pass too. Three unrelatedterminate()tests inworker.test.tsfail identically on an unmodified main debug build in this container (release passes them).cwd/nameis within a few bytes of the buffer still reaches the uncheckedload_as_filewrite in the resolver; that is resolver: bound load_as_file path before writing into its PathBuffer #35857's site and is not touched here.Background
Bun.buildresolves each entry point up front withresolve_entry_point; on failure it retries once after invalidating the resolver's cache of the entry point's directory (so a file created moments ago is found), then logs the error. The bundle runs to the linker regardless and fails at the end if the log has errors, which is why a failure that was not logged turns into a build with no entry points at all.PathBuffer([u8; MAX_PATH_BYTES]) with unchecked joins, hence the guard: a path that long cannot name a directory that exists, so there is nothing to invalidate.Worker's entry point is resolved by the same function; the worker turns whatever the resolver logged into theerrorevent's message.no test proof · iteration 0 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/bundler/bun-build-api.test.ts