Skip to content

bundler: fail the build when an entry point has no module to bundle - #38778

Open
robobun wants to merge 5 commits into
mainfrom
farm/e0dfcb75/disabled-entry-point-error
Open

bundler: fail the build when an entry point has no module to bundle#38778
robobun wants to merge 5 commits into
mainfrom
farm/e0dfcb75/disabled-entry-point-error

Conversation

@robobun

@robobun robobun commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Problem

  • bun build --target=browser ./a.ts with {"browser": {"./a.ts": false}} in the enclosing package.json aborts: panic: index out of bounds: the len is 0 but the index is 0 (release), assertion failed: chunks.len() > 0 in src/bundler/linker_context/generateChunksInParallel.rs (debug). Bun.build() with the same entry point aborts the whole process, throw: false or not.
  • With a second, live entry point the same build exits 0 and emits only the live one; the disabled entry point disappears without a message.
  • Same abort for bun build --target=browser fs / node:fs, and for a package or directory entry point whose main/index the browser field disables.
  • Cause: the resolver returns such entry points as a result whose every path is disabled, so Result::path() is None. Transpiler::resolve_entry_point (src/bundler/transpiler.rs) returned that as Ok, and BundleV2::enqueue_entry_item (src/bundler/bundle_v2.rs) returns Ok(None) for it without logging. The build drivers only check log.has_errors(), so the bundle went on to link with zero entry points, and generate_chunks_in_parallel indexes chunks[0].
  • Other ways of losing every entry point without a logged error reach the same chunks[0] (an onResolve plugin returning external: true for the entry point, the over-long specifier in bundler: log the resolve error for an entry point too long for a path buffer #38391); each producer fix only removes its own cause.

Fix

  • resolve_entry_point logs an error for a disabled result and returns Err, the contract it already has for every other entry point failure (callers skip the entry point on Err; the drivers fail the build from the log). Messages: "./a.ts" is disabled due to "browser" field in package.json (entry point), the wording bun build --no-bundle already uses for this case, and Cannot use Node.js builtin "fs" as an entry point for builtins the browser resolver stubs out (no target hint: a builtin is not a bundleable entry point under --target bun/node either, those fail with File not found).
  • Why an error rather than esbuild's empty output for the browser-field case: bun already reports it for bun build --no-bundle, the resolver represents "disabled" as "no path" on purpose (imports of the module become {}), and emitting fewer outputs than entry points with exit 0 was the silent failure mode here, so the multi-entry case needs the error anyway. esbuild errors for the builtin case too.
  • Going through resolve_entry_point covers every entry point path with one check: the CLI, Bun.build(), the plugin-declined fallback in on_resolve, and the bake callers (which pass absolute file paths and cannot hit it today).
  • Backstop for the class: generate_from_cli and run_from_js_in_new_thread now fail with None of the entry points could be bundled when parsing ends with graph.entry_points empty. Both require at least one entry point, so an empty list there always means every entry point was dropped on a path that did not log; that state now ends as a build error instead of at chunks[0], whatever the cause. The bake production driver is not changed: it already tolerates an empty chunk list on purpose. The plugin-external entry point lands on this error today; bundler: use onResolve-returned path for external imports #35053 (open) adds esbuild's specific cannot be marked as external message for it, so this PR does not carry a second copy.
  • The two CLI drivers report entry point errors after wait_for_parse() instead of returning before it, as the Bun.build() driver always has. The immediate return tore the bundle down while the runtime parse task was still starting on a worker; 26/30 ASAN runs of the CLI fix died in Worker::deinit_soon reading a Worker that get_worker_slow had published to workers_assignments before initializing it. bundler: join in-flight pool tasks before tearing the bundle down #37480 (open) makes deinit_without_freeing_arena itself join in-flight work for every driver and does not touch these lines; these two deletions keep this PR's CLI tests deterministic on main today and stay valid after it (the publication order in get_worker_slow is reported separately).
  • Coordination: bun build --no-bundle: exit 1 when an entry point does not resolve #38752 switches --no-bundle to resolve_entry_point and keeps a path_const().is_none() arm with the same message; after this PR that arm is unreachable and can go in whichever of the two lands second. bundler: log the resolve error for an entry point too long for a path buffer #38391 (over-long specifier) touches the adjacent match arm and its own test at the same spot in bun-build-api.test.ts; both rebases are trivial.
  • Verified:
    • test/bundler/bundler_browser.test.ts: browser/EntryPointDisabledByBrowserField, ...NextToLiveEntryPoint (the silent drop), ...OnlyAppliesToBrowserTarget, EntryPointDisabledByPackageMainBrowserField, EntryPointIsNodeBuiltinStubbedForBrowser (CLI, backend: "cli" so the unfixed abort stays in the child).
    • test/bundler/bundler_plugin.test.ts: a declined entry point that the browser field disables (the on_resolve fallback) gets the specific error; an entry point a plugin marks external gets the backstop error. The CLI driver calls the same helper; the only CLI-reachable zero-entry-point routes left (bun build --target=bun bun:wrap, builtins under --target bun) trip assert_file_path_is_absolute first in debug/canary builds, so the backstop is pinned through Bun.build().
    • test/bundler/bun-build-api.test.ts: Bun.build() returns success: false with the BuildMessage and rejects with an AggregateError carrying it.
    • USE_SYSTEM_BUN=1: three browser tests and both child-process tests abort with the panic above, the multi-entry test fails with "Errors were expected while bundling". bun bd test: all pass, as do the full bundler_browser, bundler_plugin, bundler_files, bundler_html, bundler_html_server, bun-build-api, bundler_edgecase, bundler_naming, cli and esbuild/packagejson files.
    • bun-debug build --target=browser ./a.ts: 30/30 runs exit 1 with the message (26/30 ASAN SEGVs with the early return still in place).

Background

  • "browser" field: a package.json map that browser builds apply during resolution; mapping a file or package to false means "this module is empty in the browser". The resolver expresses that by marking the paths of the result is_disabled, and Result::path() / path_const() skip disabled paths, so a fully disabled module resolves to a result with no path. The same representation is used for fs and node:* builtins that have no browser polyfill (those carry the node namespace). It only applies to --target browser; absolute file paths are not looked up in it.
  • Entry point pipeline: enqueue_entry_points_* resolve each entry point with resolve_entry_point and hand the result to enqueue_entry_item, which schedules a parse task and appends to graph.entry_points. The drivers (generate_from_cli for the CLI, run_from_js_in_new_thread for Bun.build()) then wait for parsing and fail the build if the log has errors; the linker requires at least one entry point, so every way of losing one has to leave an error in the log, and the new check is the last line of defense for that invariant.
  • on_resolve: when an onResolve plugin matches an entry point, its answer arrives here. NoMatch falls back to resolve_entry_point (hence the declined-plugin test); Success with external: true does nothing for entry points (the case bundler: use onResolve-returned path for external imports #35053 gives a message to).
  • wait_for_parse() spins the bundler's event loop until every scheduled parse task has completed; enqueue_entry_points_common schedules the runtime's parse task before any entry point is resolved, so on the CLI error path there was always a task in flight at teardown.
Release repro (1.4.0-canary.1)
mkdir /tmp/bf && cd /tmp/bf
echo 'export const a = 1;' > a.ts
echo 'export const b = 2;' > b.ts
echo '{"name":"x","browser":{"./a.ts":false}}' > package.json
bun build --target=browser ./a.ts            # panic: index out of bounds: the len is 0 but the index is 0 (exit 134)
bun build --target=browser ./a.ts ./b.ts --outdir=out   # exit 0, out/ contains only b.js
bun build --target=browser fs                # same panic
bun -e 'await Bun.build({entrypoints:["./a.ts"], target:"browser", throw:false})'   # same panic
bun -e 'await Bun.build({entrypoints:["./b.ts"], throw:false, plugins:[{name:"x", setup(b){ b.onResolve({filter:/b\.ts$/}, a => ({path:a.path, external:true})) }}]})'   # same panic, now the backstop error

With this branch each of these prints one error and exits 1 / returns success: false; --target=bun with the same package.json still bundles a.ts.

Earlier revision of this PR

The first revision also added esbuild's The entry point "x" cannot be marked as external error in on_resolve and had no backstop. Review turned up #35053, which already carries that error (the two conflicted on the same lines), so the arm was dropped in favor of the generic check above; the builtin message used to end with "set target to 'node' or 'bun'", which does not work for an entry point either.


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 test/bundler/bundler_plugin.test.ts

An entry point that the resolver disabled (mapped to false by a
package.json "browser" field, or a Node.js builtin that browser builds
stub out) was dropped without a log entry, as was an entry point an
onResolve plugin marked external. With a single entry point the linker
then ran with none and aborted on chunks[0]; with several, the build
succeeded with the entry point missing.

resolve_entry_point now logs an error for a disabled result and returns
Err like any other resolution failure, and on_resolve logs esbuild's
"cannot be marked as external" error for external entry points.

The CLI drivers report entry point errors after wait_for_parse() instead
of tearing the bundle down immediately: the runtime parse is already
scheduled at that point, and deinit_without_freeing_arena could observe
a Worker that get_worker_slow had published but not yet initialized.
@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 27 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0b371a18-eb08-478f-9ec4-6bbcff105b5b

📥 Commits

Reviewing files that changed from the base of the PR and between 4bf3f36 and 98f0e34.

📒 Files selected for processing (5)
  • src/bundler/bundle_v2.rs
  • src/bundler/transpiler.rs
  • test/bundler/bun-build-api.test.ts
  • test/bundler/bundler_browser.test.ts
  • test/bundler/bundler_plugin.test.ts

Comment @coderabbitai help to get the list of available commands.

@robobun

robobun commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 7:05 AM PT - Aug 15th, 2026

@robobun, your commit 98f0e34 has 1 failures in Build #97641 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 38778

That installs a local version of the PR into your bun-38778 executable, so you can run:

bun-38778 --bun

@robobun

robobun commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator Author

Status: ready for review at 98f0e34. Every lane that ran is green for this diff; two items in CI are unrelated to it.

Reproduced on 1.4.0-canary.1 (b7a0431) and on a debug build of main: with {"browser": {"./a.ts": false}} in package.json, bun build --target=browser ./a.ts and Bun.build({ entrypoints: ["./a.ts"], target: "browser" }) abort with index out of bounds: the len is 0 but the index is 0; adding a second entry point instead exits 0 with the disabled one missing. bun build --target=browser fs hits the same abort, as does an onResolve plugin returning external: true for an entry point.

Current shape: resolve_entry_point reports disabled entry points (browser field, stubbed builtins) as errors, and the CLI and Bun.build() drivers fail with None of the entry points could be bundled if every entry point was dropped without one, which is what the plugin-external case gets until #35053 adds its specific message (this PR no longer carries a copy of that arm). Tests: test/bundler/bundler_browser.test.ts (CLI), test/bundler/bundler_plugin.test.ts (declined entry point, external entry point), test/bundler/bun-build-api.test.ts (JS API); each fails against the released binary and passes with the branch build. Related open PRs: #37480 (teardown join, no overlap), #38752 (--no-bundle, its browser-field arm becomes unreachable after this), #38391 (adjacent arm, trivial rebase either way).

CI (builds 97059 for the previous revision and 97641 for this one): 176 to 177 jobs passed in each, including every lane that runs the new tests. Not green in either: the darwin 14 aarch64 - test-bun lane, which was never picked up by an agent in either build (expired in both), and in 97641 test/bake/deinitialization.test.ts segfaulting at exit on Windows 2019 x64 in dev server teardown, which this diff does not touch (reported for main separately).

Comment thread src/bundler/transpiler.rs Outdated
Comment thread src/bundler/bundle_v2.rs Outdated
Comment thread src/bundler/bundle_v2.rs Outdated
Comment thread src/bundler/bundle_v2.rs Outdated
Comment thread src/bundler/transpiler.rs Outdated
Comment thread src/bundler/transpiler.rs Outdated
Comment thread src/bundler/transpiler.rs Outdated

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional findings (outside current diff — PR may have been updated during review):

  • 🟡 src/bundler/bundle_v2.rs:3912-3918 — The new comment at lines 3914-3917 says entry-point errors are now reported after the pool drains to avoid tearing down half-initialized workers, but the ? on enqueue_entry_points_normal(...)? one line above (and on enqueue_entry_points_bake_production(...)? at line 4086) still short-circuits past wait_for_parse() if a post-schedule allocation inside it fails — the runtime parse task is dispatched at line 3292 before those ? sites. scan_module_graph_from_cli (lines 4045-4052) already has the if let Err(err) = ... { this.wait_for_parse(); return Err(err); } shape with a comment naming this exact hazard; consider mirroring it here so the invariant the new comment describes actually holds. (Trigger is OOM-only, so nit.)

    Extended reasoning...

    What the bug is

    This PR removes the has_errors() early return between enqueue_entry_points_* and wait_for_parse() in generate_from_cli (bundle_v2.rs:3912-3918) and generate_from_bake_production_cli (bundle_v2.rs:4086-4089), and adds a comment stating that entry-point errors are now reported after the pool drains because "tearing the workers down while one is still setting itself up reads a half-initialized Worker out of workers_assignments".

    However, the ? on this.enqueue_entry_points_normal(unsafe { &*entry_points })? (line 3912) and this.enqueue_entry_points_bake_production(entry_points)? (line 4086) is left unchanged and still short-circuits past wait_for_parse() when a post-schedule allocation inside those functions fails. So the invariant the new comment describes ("no return before the drain") is not actually enforced by the code one line above it.

    Code path that triggers it

    enqueue_entry_points_common() (called first at bundle_v2.rs:3045) schedules the runtime parse task on the worker pool at line 3292 and returns Ok(()):

    self.increment_scan_counter();
    self.graph.pool().schedule(runtime_parse_task);
    Ok(())

    Every subsequent ? inside enqueue_entry_points_normal runs after that task is already dispatched:

    • self.reserve_source_indexes_for_bake()? — line 3047
    • self.graph.input_files.ensure_unused_capacity(num_entry_points)? — line 3054
    • self.enqueue_entry_item(...)? — lines 3069/3073 and 3098 (which itself has input_files.append(...)? at line 2761)

    If any of these return Err, it propagates through enqueue_entry_points_normal, out through the ? at line 3912, out of the closure at line 4005, and into deinit_without_freeing_arena() at line 4014 — the exact teardown path the removed has_errors() return took, and per the PR description the one that produced 26/30 ASAN SEGVs. The same shape applies at line 4086.

    Why existing code does not prevent it

    The sibling driver scan_module_graph_from_cli (bundle_v2.rs:4045-4052) already guards this precise case, with a comment naming the same hazard:

    // enqueueEntryPoints schedules the runtime task before any fallible
    // allocation. If a later allocation fails we must still drain the
    // pool so workers aren't left holding pointers into the caller's
    // stack-allocated Transpiler.
    if let Err(err) = this.enqueue_entry_points_normal(entry_points) {
        this.wait_for_parse();
        return Err(err);
    }

    generate_from_cli and generate_from_bake_production_cli do not have this shape — they use bare ?.

    Step-by-step proof

    1. generate_from_cli calls this.enqueue_entry_points_normal(...)? at line 3912.
    2. enqueue_entry_points_normal calls enqueue_entry_points_common() at line 3045, which schedules the runtime parse task at line 3292 and returns Ok(()). A worker thread picks it up and begins get_worker_slow.
    3. enqueue_entry_points_normal then calls reserve_source_indexes_for_bake()? at line 3047. Suppose that (or ensure_unused_capacity at 3054, or input_files.append at 2761) returns Err(AllocError).
    4. The ? at line 3912 propagates Err out of the closure. wait_for_parse() at line 3918 is never reached.
    5. Control jumps to line 4005 and then to deinit_without_freeing_arena() at line 4014, which tears down the bundle while the runtime parse task is still starting on a worker.
    6. Per the PR description, that teardown is what "reads a half-initialized Worker out of workers_assignments" — the exact race the new comment says is now closed.

    Impact

    The only trigger is allocation failure on those specific ? sites — all of them are OOM paths. So the PR description's claim that "this change removes the only user-reachable way to hit it" is arguably still true in practice, and the underlying get_worker_slow publication-order bug is being fixed separately per the PR. This is why it's a nit rather than blocking.

    But: (1) the PR adds a comment at lines 3914-3917 describing an invariant the ? one line above violates, so the comment misdescribes what the code enforces; (2) the sibling function 130 lines below already has the correct shape; (3) per REVIEW.md "Fix the whole class in the same PR (same-class sites are ONE concern)", and given the PR's stated goal is closing paths to this race, mirroring the pattern is cheap and makes the comment accurate.

    Fix

    Replace the ? at lines 3912 and 4086 with the same pattern scan_module_graph_from_cli uses:

    if let Err(err) = this.enqueue_entry_points_normal(unsafe { &*entry_points }) {
        this.wait_for_parse();
        return Err(err);
    }

    and likewise for enqueue_entry_points_bake_production at line 4086.

@robobun

robobun commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator Author

On the additional finding (the ? on enqueue_entry_points_normal / enqueue_entry_points_bake_production still skipping the drain): left as is on purpose.

Everything that can fail after the runtime task is scheduled is an AllocError (reserve_source_indexes_for_bake, ensure_unused_capacity, and inside enqueue_entry_item the path_with_pretty_initialized / input_files.append calls). enqueue_entry_item calls increment_scan_counter() before those last two, so if one of them did fail, a wait_for_parse() on the way out would never see pending_items reach zero and the CLI would hang instead of exiting; making that pattern safe means balancing the counter on enqueue_entry_item's error paths as well, which is more than this PR should do for an OOM-only path (the scan_module_graph_from_cli shape has the same latent hang). The reachable case, an entry point that fails to resolve, is the one this PR drains for, and 513d393 scopes both comments to that. The publication order in get_worker_slow that makes an early teardown unsafe in the first place is filed separately.

robobun added a commit that referenced this pull request Aug 15, 2026
…-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.
…ld when no entry point survives

The onResolve external arm duplicated the error that #35053 already adds,
so it is dropped here. In its place the CLI and Bun.build drivers fail
with "None of the entry points could be bundled" when parsing ends with
an empty entry point list, so any remaining way of dropping every entry
point without logging becomes a build error instead of indexing an empty
chunk list. The builtin entry point message no longer suggests another
target, since a builtin cannot be an entry point for any target.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks — the doc-comment concern I raised earlier is resolved (the sentence is gone), and the new fail_if_no_entry_points backstop in 98f0e34 means the over-long-specifier arm I flagged now lands on "None of the entry points could be bundled" instead of the chunks[0] panic even before #38391 lands, so that thread is fully closed from my side.

I reviewed the current revision and didn't find any bugs. Given the coordination with four open PRs (#35053, #37480, #38391, #38752), the deliberate divergence from esbuild's empty-output behavior for browser-disabled entry points, and the removal of the pre-wait_for_parse() early return in the two CLI drivers to work around the get_worker_slow publication race, a human look would still be worthwhile.

What was reviewed

  • reject_disabled_entry_point — checked that path_const().is_none() is the right predicate (it skips disabled paths) and that the node namespace branch matches how the resolver tags stubbed builtins.
  • The three driver call sites for fail_if_no_entry_points() — placed after has_errors() so no double error; bake production intentionally excluded per description.
  • The removed early returns — confirmed run_from_js_in_new_thread already had this shape, so the CLI drivers now match; the remaining ? on enqueue_entry_points_* is AllocError-only (author's 01:35 note).
  • Tests follow harness conventions (tempDir, test.concurrent, subprocess drain via Promise.all, exit code asserted last, backend: "cli" to isolate the abort).
Extended reasoning...

Overview

This PR fixes a process abort (index out of bounds: the len is 0 but the index is 0 / assertion failed: chunks.len() > 0) that occurs when every entry point resolves to a module the browser resolver has disabled (via a package.json "browser": {"./x": false} map or a stubbed Node builtin like fs). It touches two Rust files in the bundler core (src/bundler/transpiler.rs, src/bundler/bundle_v2.rs) and three test files. The fix has three parts: (1) resolve_entry_point now routes Ok results through a new reject_disabled_entry_point helper that logs an error and returns Err when path_const() is None; (2) a fail_if_no_entry_points() backstop in generate_from_cli and run_from_js_in_new_thread that catches any remaining path that drops every entry point without logging; (3) the two CLI drivers now defer their entry-point-error check until after wait_for_parse(), matching the existing JS driver, to avoid tearing down the pool while a worker is still being published in get_worker_slow (26/30 ASAN SEGVs otherwise).

Security risks

None. This is an error-reporting path in the bundler; no auth, crypto, network, or untrusted-input parsing is touched. The new error messages echo the user-supplied entry-point specifier via bstr::BStr::new(entry_point), which is the same pattern the existing ModuleNotFound arm uses.

Level of scrutiny

Moderate-to-high. The bundler's build-driver control flow is a critical path, and this PR both adds new failure branches and removes two existing early returns. The removal is justified as a workaround for a threading race that a separate PR (#37480) fixes properly, and the author has verified 30/30 clean runs with the change vs 26/30 SEGVs without — but it does mean more parse work runs before a resolution error surfaces, and the shape depends on #37480 not later changing these same lines. The PR also makes a user-facing API choice (error out instead of esbuild's empty-output behavior for a browser-disabled entry point) that the description argues for but a maintainer should sign off on.

Other factors

  • Prior review loop: I previously flagged that a doc comment overstated the "every Err is logged" contract given the pre-existing MAX_PATH_BYTES guard arm. The author removed the doc sentence, pointed to #38391 which restructures that arm, and — in the latest commit — added the fail_if_no_entry_points backstop, which independently prevents that arm from reaching the chunks[0] panic. That concern is fully addressed.
  • PR coordination: The description explicitly coordinates with four open PRs (#35053 external-entry-point message, #37480 pool teardown join, #38391 over-long specifier, #38752 --no-bundle switch). Each interaction is called out and the rebase is described as trivial, but a maintainer should confirm the landing order is what they want.
  • Test coverage: Five new itBundled CLI tests in bundler_browser.test.ts (single/multi entry, bun target negative, package-main variant, node-builtin variant), one subprocess test each in bun-build-api.test.ts (JS API, both throw: false and thrown paths) and bundler_plugin.test.ts (declined-then-disabled and plugin-external → backstop). All spawn subprocesses so the pre-fix abort stays contained; all follow the repo's harness conventions. The author reports USE_SYSTEM_BUN=1 failures and bun bd test passes across the affected files.
  • comment-cop bot: Flagged six long comments; the author cut each to one line in 6c215c1 and the current diff's comments are appropriately terse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant