perl-vfs: fix image build overflow that masked ENOSPC as a parent-dir ENOENT#829
Open
brandonpayton wants to merge 1 commit into
Conversation
… ENOENT The Perl 5.40 stdlib payload (~26 MiB across 1288 files) overflowed the fixed 16 MiB SharedArrayBuffer in build-perl-vfs-image.ts. The out-of-space error from mkdir was swallowed by ensureDir's catch-all, so it resurfaced as a confusing "No such file or directory" (ENOENT) at pathResolveParent when a later write could not resolve its never-created parent (kd-n6vr; discovered in kd-gtxa browser verification). No file/dir name collision exists in the merged stdlib namespace, ruling out a perl-src-state artifact. - build-perl-vfs-image.ts: use a growable SharedArrayBuffer (64 MiB init, 256 MiB max) like the mariadb/redis/sqlite image builders, so the full stdlib fits and can grow. perl.vfs.zst is produced again (64 MB raw -> 3.4 MB zstd). - image-helpers.ts: ensureDir and symlink now swallow only EEXIST and rethrow every other error (ENOSPC/ENOTDIR/ENOENT), so a real failure is reported at its true origin instead of being masked -- per CLAUDE.md "prefer truthful failure over convenient illusion". - vfs-image.test.ts: regression tests for the honest-failure contract. Verification: original crash reproduced in-worktree; fix rebuilds perl.vfs.zst; 4 new host tests pass; full host vitest shows +4 passed / 0 new failures vs a clean baseline (29 pre-existing kernel/wasm failures identical). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase B-1 matrix build status —
|
| Package | Arch | Status | Sha |
|---|---|---|---|
| libcurl | wasm32 | built | b01be826 |
| libcxx | wasm32 | built | bd2dd5a6 |
| libcxx | wasm64 | built | 926cfc96 |
| libpng | wasm32 | built | 25e56ef0 |
| libxml2 | wasm32 | built | eb77d16a |
| libxml2 | wasm64 | built | 9743c3c9 |
| openssl | wasm32 | built | 296793ae |
| openssl | wasm64 | built | b53a16d9 |
| sqlite | wasm32 | built | 93b98c80 |
| sqlite | wasm64 | built | 7079a1ac |
| zlib | wasm32 | built | 4543740c |
| zlib | wasm64 | built | 4ccf5221 |
| bc | wasm32 | built | 0c54e287 |
| bzip2 | wasm32 | built | 614536d6 |
| coreutils | wasm32 | built | e1a33298 |
| curl | wasm32 | built | ecbc3967 |
| dash | wasm32 | built | 4f2caf8b |
| diffutils | wasm32 | built | 34f174f8 |
| dinit | wasm32 | built | 97a7849b |
| fbdoom | wasm32 | built | 3799bb5e |
| file | wasm32 | built | 535dd689 |
| findutils | wasm32 | built | 4b727dbf |
| gawk | wasm32 | built | 92e5184d |
| git | wasm32 | built | 42b4d1cb |
| grep | wasm32 | built | fd4d79fa |
| gzip | wasm32 | built | 8f54d8ac |
| kandelo-sdk | wasm32 | built | 3829dcd2 |
| kernel | wasm32 | built | 917959d2 |
| less | wasm32 | built | 7f3184f8 |
| lsof | wasm32 | built | 4dc5ae5b |
| m4 | wasm32 | built | 5fbbe8b3 |
| make | wasm32 | built | 57a6d854 |
| mariadb | wasm32 | built | 9ed4aa94 |
| mariadb | wasm64 | built | eaf29411 |
| modeset | wasm32 | built | d9f12284 |
| msmtpd | wasm32 | built | 23172a3a |
| nano | wasm32 | built | 763f56f8 |
| ncurses | wasm32 | built | a7862ee0 |
| netcat | wasm32 | built | 57bdd0cd |
| nginx | wasm32 | built | 933bdcd3 |
| php | wasm32 | built | e047ea3c |
| posix-utils-lite | wasm32 | built | 2aec933c |
| sed | wasm32 | built | 9d958a03 |
| spidermonkey | wasm32 | built | ef0ac7d5 |
| tar | wasm32 | built | 050e7cb3 |
| tcl | wasm32 | built | ee9ae67a |
| unzip | wasm32 | built | b176c19f |
| userspace | wasm32 | built | a9e013a2 |
| vim | wasm32 | built | 8194ff88 |
| wget | wasm32 | built | 378dca44 |
| xz | wasm32 | built | 763b854c |
| zip | wasm32 | built | 1c834314 |
| zstd | wasm32 | built | bcd693e5 |
| bash | wasm32 | built | d435c352 |
| mariadb-test | wasm32 | built | 74e71062 |
| mariadb-vfs | wasm32 | built | 85427981 |
| mariadb-vfs | wasm64 | built | 6c3ac528 |
| nethack | wasm32 | built | 5b7fc658 |
| node | wasm32 | built | cdad27ac |
| spidermonkey-node | wasm32 | built | 6d8dc738 |
| vim-browser-bundle | wasm32 | built | ef862c6f |
| nethack-browser-bundle | wasm32 | built | d4992e6b |
| rootfs | wasm32 | built | ae3df667 |
| shell | wasm32 | built | 82682bda |
| lamp | wasm32 | built | 43815b7e |
| node-vfs | wasm32 | built | fd9e7949 |
| wordpress | wasm32 | built | a1d15adb |
Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Building the browser Perl VFS image (
bash images/vfs/scripts/build-perl-vfs-image.sh) crashed withSFSError: No such file or directoryatpathResolveParent, and noperl.vfs.zstwas produced (kd-n6vr; discovered during kd-gtxa browser verification). This restores the build and, more importantly, makes the underlying failure mode honest.Root cause (a product bug, not a perl-src artifact)
The builder allocated a fixed, non-growable 16 MiB
SharedArrayBuffer, but the Perl 5.40.3 stdlib payload is ~25.68 MiB across 1288 files (+238 dirs). The in-memory VFS ran out of space mid-write; theENOSPCfrommkdirin the parent-dir loop was silently swallowed byensureDir's catch-all, so the directory was never created and the failure resurfaced far away as a misleadingENOENTwhen the next file write could not resolve its missing parent.Static analysis of the merged
PRIVLIBnamespace reproduced exactly 1288 included paths and found zero file/dir name collisions, ruling out the perl-src-layout hypothesis.pathResolveParentthrew-2 (ENOENT)(parent path unresolved), not-20 (ENOTDIR)(file-in-the-way) — consistent with a masked, never-created parent.Changes
images/vfs/scripts/build-perl-vfs-image.ts— allocate a growableSharedArrayBuffer(64 MiB, { maxByteLength: 256 MiB })+create(sab, 256 MiB), matching themariadb/redis/sqliteimage builders. The full stdlib fits (and can grow); the empty tail compresses away (64 MB raw → 3.4 MB zstd).host/src/vfs/image-helpers.ts—ensureDirandsymlinknow swallow onlyEEXISTand rethrow every other error, so a real failure (ENOSPC/ENOTDIR/ENOENT) is reported at its true origin instead of being masked. Per CLAUDE.md: prefer truthful failure over convenient illusion.host/test/vfs-image.test.ts— 4 regression tests pinning the honest-failure contract.Verification
ENOENTatpathResolveParent, code-2, while "Writing 1288 files to VFS".apps/browser-demos/public/perl.vfs.zstproduced (64.0 MB raw → 3.4 MB zstd).cd host && npx vitest run): 586 passed / 29 failed / 204 skipped with the fix vs 582 / 29 / 201 on a clean baseline → +4 passed (the new tests), 0 new failures. The 29 failures are an identical pre-existing set (kernel/spawn/pthread/wasm/wasi suites needing builtkernel.wasm/example binaries absent from this worktree) — unrelated to this change.Durable evidence:
test-runs/kd-n6vr/DISPOSITION.mdandtest-runs/kd-n6vr/outcome-lists/.Scope / follow-ups
perl.vfs.zst; booting perl in-browser remains kd-yuef/kd-gtxa scope (gated on trusted-CI GHCR bottle publish). No browser smoke run here.erlang(16 MiB) andpython(32 MiB) VFS builders still use non-growable buffers; with the now-honestensureDira future overflow there fails loudly asENOSPC. Candidate follow-up to adopt the growable pattern proactively.🤖 Generated with Claude Code