Skip to content

init: fix the default package name in a filesystem root and directly below / - #43489

Open
robobun wants to merge 4 commits into
mainfrom
robobun/98c4d534/init-name-at-drive-root
Open

robobun wants to merge 4 commits into
mainfrom
robobun/98c4d534/init-name-at-drive-root

Conversation

@robobun

@robobun robobun commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

  • bun init -y writes an invalid default package name: "name": "/app" in /app (any directory directly below the POSIX root), "name": "/" in /, and "name": "u:" in the Windows drive root U:\.
  • src/runtime/cli/init_command.rs:397 took the name from PathName::init(cwd).filename. When the path has no parent directory component, filename is the whole path. On Windows the cwd came from FileSystem::top_level_dir_without_trailing_slash() (src/resolver/lib.rs:425), which turned C:\ into C:.
  • bun repl reads the same accessor. In U:\, module.path is U:. In /, module.filename is //[repl].

Fix

  • bun init takes the name from bun_paths::basename(cwd). It is empty for a root, so the existing project fallback applies.
  • The accessor keeps a Windows filesystem root (C:\), as it already kept /.
  • Bun__REPL__setupGlobalRequire adds no second separator to a cwd that ends in one. bun patch strips the separator itself, so the path it prints does not change.
  • Verified: the new tests in test/cli/init/init.test.ts (Windows) and test/js/bun/repl/repl.test.ts fail on canary 1.4.3. Both files and test/cli/install/bun-patch.test.ts pass on Linux and Windows x64 debug builds.

Background

  • C: without a separator is a drive-relative path. It names the current directory of drive C, not the root C:\.
  • top_level_dir is the cwd that FileSystem::init reads once. It has no trailing separator, except for a root.
  • subst U: <dir> makes a directory the root of a new drive, without admin rights. A test cannot write to the root of a real drive.
Notes

Values before and after (canary 1.4.3-canary.1+26e7a4b36, then debug builds of this branch)

cwd what before after
/initx bun init -y name /initx initx
/ bun init -y name / project
U:\ (subst) bun init -y name u: project
U:\ (subst) bun repl module.path U: U:\
/ bun repl module.filename //[repl] /[repl]
  • The README heading gets the same text as the name.
  • The two POSIX bun init rows have no test, because a test cannot write to /. I checked them by hand in a container, before and after. Bun 1.2.20 gives the same /initx, so the bug is not new.
  • What CI does cover for them: unit tests in src/paths/lib.rs pin the basename results that the fix depends on (empty for /, C:\ and C:, app for /app). They run in the cargo miri test check. They do not run bun init. A test gated on root would be skipped in CI: the Linux lanes I checked (debian 13 x64-asan, alpine 3.23 aarch64) run the tests as buildkite-agent.
  • npm init -y (npm 11.16.0) writes "name": "" in U:\. project is the name that bun init already uses when the normalized directory name is empty.
  • The accessor has two other readers. bun link (src/runtime/cli/link_command.rs:174) reads it after PackageManager::init has already stripped the cwd to C: (src/install/PackageManager.rs:1509, :1840). So this change does not reach bun link. In a drive root it still fails in init with ENOENT, on main and on this branch. install: make bun install work in the root of a Windows drive #43437 fixes that path.
  • bun patch (src/install/PackageManager/patchPackage.rs:977) joined the accessor with platform::Posix to print a path. With C:\ kept, that join would print C:\/node_modules/... So bun patch now strips the separator itself and prints C:/node_modules/.., as before.
  • top_level_dir comes from getcwd. So the accessor only strips something in a drive root, or after process.chdir() (VirtualMachine::set_process_cwd appends a separator).
  • The accessor uses windows_filesystem_root, not without_trailing_slash_windows_path. The second one also strips \ on POSIX, where \ can end a directory name.
  • install: make bun install work in the root of a Windows drive #43437 makes bun install work in a drive root. Until it lands, the bun install step at the end of bun init fails there with ENOENT, and bun init still exits 0. The new init test starts from a package.json that needs no install, so it does not depend on install: make bun install work in the root of a Windows drive #43437 and does not use the network. substDrive in test/harness.ts is the same text as the helper in install: make bun install work in the root of a Windows drive #43437, so the two branches merge without a conflict.
  • Suites run on debug builds: test/cli/init/init.test.ts, test/js/bun/repl/repl.test.ts and test/cli/install/bun-patch.test.ts on Linux x64 and Windows x64, test/internal/source-lints/ on Linux. cargo test -p bun_paths --lib and bun run rust:miri -p bun_paths on Linux (31 tests pass). test/cli/install/bun-link.test.ts on Linux: 3 of 4 pass. The fourth compares exact stdout, and a debug build prints a stack trace there (#[cfg(bun_debug)] in src/install/PackageInstall.rs:221).

no test proof · iteration 2 · platform-specific test(s) that do not run on this machine, deferring to CI, which covers all platforms: test/js/bun/repl/repl.test.ts, test/cli/init/init.test.ts

…below `/`

`bun init` took the default package name from
`PathName::init(cwd).filename`. When the path has no parent directory
component, that is the whole path: `bun init -y` wrote `"name": "/app"`
in `/app`, `"name": "/"` in `/`, and `"name": "u:"` in `U:\`. The name
now comes from `bun_paths::basename`. It is empty for a root, so the
existing `project` fallback applies.

`FileSystem::top_level_dir_without_trailing_slash` turned the drive
root `C:\` into `C:`, the current directory of drive C. It now keeps a
Windows filesystem root, as it already kept `/`. `bun repl` read it for
`module.path`, which was `U:` in `U:\`.

`Bun__REPL__setupGlobalRequire` adds no second separator to a cwd that
ends in one. `module.filename` was `//[repl]` in `/`.

`bun patch` strips the separator itself, so the path it prints does
not change.
@coderabbitai

coderabbitai Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: oven-sh/bun/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Essentials

Run ID: 370f4603-ea57-4726-b87b-e0b2c54ff092

📥 Commits

Reviewing files that changed from the base of the PR and between 26e7a4b and a77ab75.

📒 Files selected for processing (7)
  • src/install/PackageManager/patchPackage.rs
  • src/jsc/bindings/ExposeNodeModuleGlobals.cpp
  • src/resolver/lib.rs
  • src/runtime/cli/init_command.rs
  • test/cli/init/init.test.ts
  • test/harness.ts
  • test/js/bun/repl/repl.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 0 remain after this review.


Walkthrough

The changes preserve filesystem roots when removing trailing separators. Package initialization, REPL setup, and workspace patch instructions now use root-safe paths. Windows regression tests cover drive-root behavior.

Changes

Filesystem root path handling

Layer / File(s) Summary
Preserve filesystem roots
src/resolver/lib.rs
top_level_dir_without_trailing_slash preserves Windows filesystem roots while removing trailing separators from longer paths.
Update path consumers
src/runtime/cli/init_command.rs, src/jsc/bindings/ExposeNodeModuleGlobals.cpp, src/install/PackageManager/patchPackage.rs
Package initialization derives names from the top-level directory. REPL filenames avoid duplicate separators. Workspace patch instructions use the updated path handling.
Add root regression coverage
test/harness.ts, test/cli/init/init.test.ts, test/js/bun/repl/repl.test.ts
Tests use substDrive to verify Windows drive-root behavior for bun init and the REPL. The helper cleans up substituted drives.

Suggested reviewers: dylan-conway

Priority: ➖ Normal

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the main change: fixing the default package name for filesystem roots and directories directly below the POSIX root.
Description check ✅ Passed The description explains the problem, implementation, platform-specific behavior, testing, and known limitations. It does not use the exact template headings, but it provides the required information …

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

@robobun

robobun commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 3:43 PM PT - Sep 19th, 2026

✅ @robobun, your commit 297f45751bf62f1688ea6c7bca4c043845106d4f passed in Build #118540! 🎉


🧪   To try this PR locally:

bunx bun-pr 43489

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

bun-43489 --bun

@robobun

robobun commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status

Reproduction:

  • Windows x64, canary 1.4.3-canary.1+26e7a4b36: subst U: <dir>, then bun init -y in U:\. The package.json has "name": "u:".
  • Linux x64, same canary and Bun 1.2.20: bun init -y in /initx gives "name": "/initx", and in / it gives "name": "/".
  • bun repl in U:\ has module.path equal to U:. In / it has module.filename equal to //[repl].

Fix:

  • This PR. The two new tests fail on the canary and pass on Linux x64 and Windows x64 debug builds.
  • The POSIX bun init cases have no test, because a test cannot write to /. I checked them by hand, before and after.
  • Review: the full adversarial review of this diff did not complete. It was interrupted three times and returned no result. I reviewed the diff directly with two read-only passes instead. They found no regression. They led to two changes: the REPL test no longer makes an unused temp directory on POSIX, and the Notes no longer claim an effect on bun link (that path fails earlier, in PackageManager::init, and install: make bun install work in the root of a Windows drive #43437 fixes it).

CI (build 118394 on f3320c68b8, finished, 180 of 181 jobs passed):

Later commits (no behavior change):

  • 5cdb6adf57 and a77ab75c6c shorten three code comments that the reviews found inexact or too long. On a Linux debug build I ran the new REPL test before each push, plus test/cli/init/init.test.ts before 5cdb6adf57 and the two bun patch tests that print the joined path before a77ab75c6c.
  • 297f45751b is the head. It adds unit tests in src/paths/lib.rs for the basename results that the fix depends on (empty for /, C:\ and C:). They pass under cargo test -p bun_paths --lib and under Miri (31 tests), and they run in the cargo miri test check. They do not run bun init, so the two POSIX bun init cases still have no end-to-end test. A test gated on root would be skipped in CI: the two Linux lanes I checked run the tests as buildkite-agent.

The red x64-asan lane, checked again on build 118499 (a77ab75c6c):

  • test/js/bun/spawn/spawn.test.ts is red there again, in the same test group. The other failures in that build passed on a retry when I looked (10 of 181 jobs were still open).
  • The same test group is red on the same lane in 8 of the last 14 failed builds of other branches today: 118364, 118379, 118399, 118400, 118408, 118414, 118416, 118426. Those changes are unrelated to this one (HTTP/2, WebSocket proxy, shell, process signals). So the red lane does not come from this diff.
  • Build 118462 (5cdb6adf57) had test/bake/deinitialization.test.ts red on alpine 3.23 aarch64, all four attempts, with expect(liveServerWrappers()).toBe(serverWrapperBaseline). The same test failed on the same lane in main's build 118148 and passed on its retry there. In build 118499 it passed on a retry. I reported both tests for triage.

@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.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Comment thread src/runtime/cli/init_command.rs Resolved
The comment read as a rule for every filesystem root. The basename is empty in `/` and in a drive root. A UNC share root gives the share name.
Comment thread src/resolver/lib.rs Resolved

@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.

Code review found no issues

No high-confidence issues detected in this change.

@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.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Comment thread test/cli/init/init.test.ts Resolved
`bun init` takes the default package name from `bun_paths::basename` and relies on the empty result for `/`, `C:\` and `C:`. Nothing tested that. The functions are pure, so the Windows rules run on every host.

@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.

Code review found no issues

No high-confidence issues detected in this change.

This branch has not been deployed

No deployments
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