Skip to content

Conversation

@robobun
Copy link
Collaborator

@robobun robobun commented Nov 24, 2025

Summary

Fixes #11295

The glob walker's DirEntryAccessor was using the lowercase map key instead of the case-preserved filename stored in the Entry. This caused ENOENT errors when trying to open directories with mixed-case names like BuildIconList because it would try to open buildiconlist.

Root Cause

In src/fs.zig, the DirEntry.EntryMap stores entries with lowercase keys for case-insensitive lookups:

try dir.data.put(allocator, stored.base_lowercase(), stored);

But the Entry also stores the original case-preserved name in base_. The glob walker was incorrectly using the map key (key_ptr.*) instead of entry.base().

The Fix

Changed DirEntryAccessor.DirIter.next() to use entry.base() instead of key_ptr.*:

const entry = nextval.value_ptr.*;
const name = entry.base();  // case-preserved name

Test plan

  • Added regression test in test/regression/issue/11295.test.ts
  • Test passes with bun bd test test/regression/issue/11295.test.ts
  • Test fails with USE_SYSTEM_BUN=1 bun test test/regression/issue/11295.test.ts
  • Verified fix works with https://github.com/ProCode-Software/proicons repo (mentioned in issue)

🤖 Generated with Claude Code

@robobun
Copy link
Collaborator Author

robobun commented Nov 24, 2025

Updated 5:49 PM PT - Nov 23rd, 2025

❌ Your commit 3f3aa2a2 has 6 failures in Build #32288 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 25008

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

bun-25008 --bun

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 24, 2025

Walkthrough

Replaced lowercase-key-based name/type retrieval with direct DirEntry access in glob walker to preserve original case and use entry.kind for file type. Added regression tests exercising bun run --filter with mixed-case and path-filtered workspaces and a Glob case-preservation check.

Changes

Cohort / File(s) Summary
GlobWalker directory entry retrieval
src/glob/GlobWalker.zig
Use entry.base() for entry names (preserves original case) and entry.kind(...) to determine file type instead of reading from a lowercase key and value pointer.
Regression tests for workspace filtering and Glob case
test/regression/issue/11295.test.ts
Add tests covering bun run --filter with mixed-case directory names, path-filtered runs, and a Glob scan asserting case-preserved file paths and no ENOENT errors.

Suggested reviewers

  • nektro
  • pfgithub

Pre-merge checks

✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the primary change: fixing the glob walker to preserve directory name case when looking up entries.
Description check ✅ Passed The PR description comprehensively covers the issue, root cause, fix details, and test plan with verification steps matching the provided template.
Linked Issues check ✅ Passed The PR directly addresses issue #11295 by fixing the ENOENT error caused by using lowercase keys instead of case-preserved names when accessing directory entries.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the glob walker case sensitivity issue: DirEntryAccessor modification and regression test addition directly support the objective.

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 31d1992 and 3f3aa2a.

📒 Files selected for processing (2)
  • src/glob/GlobWalker.zig (1 hunks)
  • test/regression/issue/11295.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (13)
📚 Learning: 2025-10-19T02:44:46.354Z
Learnt from: theshadow27
Repo: oven-sh/bun PR: 23798
File: packages/bun-otel/context-propagation.test.ts:1-1
Timestamp: 2025-10-19T02:44:46.354Z
Learning: In the Bun repository, standalone packages under packages/ (e.g., bun-vscode, bun-inspector-protocol, bun-plugin-yaml, bun-plugin-svelte, bun-debug-adapter-protocol, bun-otel) co-locate their tests with package source code using *.test.ts files. This follows standard npm/monorepo patterns. The test/ directory hierarchy (test/js/bun/, test/cli/, test/js/node/) is reserved for testing Bun's core runtime APIs and built-in functionality, not standalone packages.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-10-26T01:32:04.844Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 24082
File: test/cli/test/coverage.test.ts:60-112
Timestamp: 2025-10-26T01:32:04.844Z
Learning: In the Bun repository test files (test/cli/test/*.test.ts), when spawning Bun CLI commands with Bun.spawnSync for testing, prefer using stdio: ["inherit", "inherit", "inherit"] to inherit stdio streams rather than piping them.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-11-14T16:07:01.064Z
Learnt from: RiskyMH
Repo: oven-sh/bun PR: 24719
File: docs/bundler/executables.mdx:527-560
Timestamp: 2025-11-14T16:07:01.064Z
Learning: In the Bun repository, certain bundler features like compile with code splitting (--compile --splitting) are CLI-only and not supported in the Bun.build() JavaScript API. Tests for CLI-only features use backend: "cli" flag (e.g., test/bundler/bundler_compile_splitting.test.ts). The CompileBuildConfig interface correctly restricts these with splitting?: never;. When documenting CLI-only bundler features, add a note clarifying they're not available via the programmatic API.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-10-18T23:43:42.502Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 23817
File: src/js/node/test.ts:282-282
Timestamp: 2025-10-18T23:43:42.502Z
Learning: In the Bun repository, the error code generation script (generate-node-errors.ts) always runs during the build process. When reviewing code that uses error code intrinsics like $ERR_TEST_FAILURE, $ERR_INVALID_ARG_TYPE, etc., do not ask to verify whether the generation script has been run or will run, as it is automatically executed.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-10-19T02:52:37.412Z
Learnt from: theshadow27
Repo: oven-sh/bun PR: 23798
File: packages/bun-otel/tsconfig.json:1-15
Timestamp: 2025-10-19T02:52:37.412Z
Learning: In the Bun repository, packages under packages/ (e.g., bun-otel) can follow a TypeScript-first pattern where package.json exports point directly to .ts files (not compiled .js files). Bun natively runs TypeScript, so consumers import .ts sources directly and receive full type information without needing compiled .d.ts declaration files. For such packages, adding "declaration": true or "outDir" in tsconfig.json is unnecessary and would break the export structure.
<!-- [remove_learning]
ceedde95-980e-4898-a2c6-40ff73913664

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-09-12T18:16:50.754Z
Learnt from: RiskyMH
Repo: oven-sh/bun PR: 22606
File: src/glob/GlobWalker.zig:449-452
Timestamp: 2025-09-12T18:16:50.754Z
Learning: For Bun codebase: prefer using `std.fs.path.sep` over manual platform separator detection, and use `bun.strings.lastIndexOfChar` instead of `std.mem.lastIndexOfScalar` for string operations.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-10-25T17:20:19.041Z
Learnt from: theshadow27
Repo: oven-sh/bun PR: 24063
File: test/js/bun/telemetry/server-header-injection.test.ts:5-20
Timestamp: 2025-10-25T17:20:19.041Z
Learning: In the Bun telemetry codebase, tests are organized into two distinct layers: (1) Internal API tests in test/js/bun/telemetry/ use numeric InstrumentKind enum values to test Zig↔JS injection points and low-level integration; (2) Public API tests in packages/bun-otel/test/ use string InstrumentKind values ("http", "fetch", etc.) to test the public-facing BunSDK and instrumentation APIs. This separation allows internal tests to use efficient numeric enums for refactoring flexibility while the public API maintains a developer-friendly string-based interface.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-11-06T00:58:23.965Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 24417
File: test/js/bun/spawn/spawn.test.ts:903-918
Timestamp: 2025-11-06T00:58:23.965Z
Learning: In Bun test files, `await using` with spawn() is appropriate for long-running processes that need guaranteed cleanup on scope exit or when explicitly testing disposal behavior. For short-lived processes that exit naturally (e.g., console.log scripts), the pattern `const proc = spawn(...); await proc.exited;` is standard and more common, as evidenced by 24 instances vs 4 `await using` instances in test/js/bun/spawn/spawn.test.ts.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-11-07T17:28:51.204Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 24423
File: test/js/node/path/browserify.test.js:472-475
Timestamp: 2025-11-07T17:28:51.204Z
Learning: In test files under test/js/node/path/, markovejnovic prefers functional programming patterns (e.g., reduce, map, filter chains) over imperative loops for clarity and readability.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-11-08T04:06:33.198Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 24491
File: test/js/bun/transpiler/declare-global.test.ts:17-17
Timestamp: 2025-11-08T04:06:33.198Z
Learning: In Bun test files, `await using` with Bun.spawn() is the preferred pattern for spawned processes regardless of whether they are short-lived or long-running. Do not suggest replacing `await using proc = Bun.spawn(...)` with `const proc = Bun.spawn(...); await proc.exited;`.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-10-01T22:13:08.081Z
Learnt from: taylordotfish
Repo: oven-sh/bun PR: 23169
File: src/codegen/bindgenv2/internal/base.ts:120-125
Timestamp: 2025-10-01T22:13:08.081Z
Learning: Iterator.some() and other Iterator helper methods (map, filter, etc.) are supported in Bun and modern Node.js (22+) runtimes and can be safely used on string iterators and other iterator objects.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-10-08T13:48:02.430Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 23373
File: test/js/bun/tarball/extract.test.ts:107-111
Timestamp: 2025-10-08T13:48:02.430Z
Learning: In Bun's test runner, use `expect(async () => { await ... }).toThrow()` to assert async rejections. Unlike Jest/Vitest, Bun does not require `await expect(...).rejects.toThrow()` - the async function wrapper with `.toThrow()` is the correct pattern for async error assertions in Bun tests.

Applied to files:

  • test/regression/issue/11295.test.ts
📚 Learning: 2025-11-11T22:55:08.547Z
Learnt from: pfgithub
Repo: oven-sh/bun PR: 24571
File: src/css/values/url.zig:97-116
Timestamp: 2025-11-11T22:55:08.547Z
Learning: In Zig 0.15, the standard library module `std.io` was renamed to `std.Io` (with capital I). Code using `std.Io.Writer.Allocating` and similar types is correct for Zig 0.15+.

Applied to files:

  • src/glob/GlobWalker.zig
🧬 Code graph analysis (1)
test/regression/issue/11295.test.ts (2)
test/harness.ts (2)
  • tempDir (277-284)
  • bunExe (102-105)
scripts/glob-sources.mjs (1)
  • glob (11-11)
🔇 Additional comments (2)
src/glob/GlobWalker.zig (1)

211-227: Case-preserved DirEntry name usage looks correct

Switching from the lowercase map key to entry.base() and deriving kind from entry.kind(&FS.instance.fs, true) correctly preserves the original directory name casing while keeping the existing type semantics. The iterator contract (IterResult.name.slice() and IterResult.kind) remains intact, so this should resolve the ENOENT regression without side effects.

test/regression/issue/11295.test.ts (1)

4-102: Regression tests comprehensively cover the mixed-case glob behavior

The two bun run --filter tests nicely reproduce the original ENOENT scenarios (wildcard filter and explicit path filter) and assert both absence of ENOENT and correct script execution. The Bun.Glob coverage test also locks in the expectation that directory casing is preserved in returned paths while avoiding traversal-order flakiness via results.sort(). Use of tempDir, await using proc = Bun.spawn(...), and piped stdio is consistent with existing Bun test patterns and appropriate for asserting output.


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

Fixes #11295

The glob walker's DirEntryAccessor was using the lowercase map key
instead of the case-preserved filename stored in the Entry. This
caused ENOENT errors when trying to open directories with mixed-case
names like "BuildIconList" because it would try to open "buildiconlist".

The fix uses entry.base() to get the original case-preserved name
instead of the lowercase key used for case-insensitive lookups.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@robobun robobun force-pushed the claude/fix-glob-case-sensitivity-11295 branch from 31d1992 to 3f3aa2a Compare November 24, 2025 01:06
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.

bun --filter gives (error: ENOENT)

2 participants