Skip to content

fix(sync): avoid canonicalize on WASI preopened dirs#79

Merged
lwshang merged 1 commit into
mainfrom
fix/wasi-canonicalize-nested-dir
Jun 7, 2026
Merged

fix(sync): avoid canonicalize on WASI preopened dirs#79
lwshang merged 1 commit into
mainfrom
fix/wasi-canonicalize-nested-dir

Conversation

@lwshang

@lwshang lwshang commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator

Ports the WASI canonicalize fix from the migration branch (#71) to main.

Problem

The sync plugin's scan step canonicalized the manifest dir. On wasm32-wasip2, Path::canonicalize calls realpath, which returns ENOENT for any path beneath a preopen whose WASI guest name has more than one component (e.g. src/frontend/dist) — even though read_dir/metadata/read through that preopen work fine. So a nested dir failed:

failed to run plugin
  caused by: plugin returned error: canonicalize src/frontend/dist: No such file or directory (os error 44)

Single-component dirs like dist happened to canonicalize to /dist and worked, which is why the existing fixtures never caught it. (Originally reported on the forum against the migration recipe; same root cause lives here.)

Fix

Build the scan root by prepending / to the (host-validated, relative, ..-free) manifest dir instead of canonicalizing. This yields the same shape canonicalize produced for single-component dirs (/dist, /src/frontend/dist) and uses only plain wasi:filesystem ops the preopen supports. main's scan() had a single canonicalize call; walk already uses read_dir paths rooted at that dir, and _headers/_redirects load via relative paths — none of which need canonicalization.

Test

Adds an e2e fixture + nested_dir_deploy test using dirs: [src/frontend/dist] with a nested subdir asset. Verified it fails with the exact error above when the fix is reverted, and passes with it.

  • cargo test -p sync-core — 188 pass
  • cargo test -p e2e --test sync — 7 pass (incl. nested regression)
  • cargo clippy -p sync-core — clean

Note: this is the same fix already shipped on migration as migration-v2.2.1 (consumed by asset-canister-v2.2.1).

The sync plugin's scan step called `Path::canonicalize` on the manifest
`dir`. On wasm32-wasip2 that calls `realpath`, which returns ENOENT for
any path under a preopen whose guest name has more than one component
(e.g. `src/frontend/dist`), even though ordinary access works. Nested
`dir`s therefore failed with "canonicalize src/frontend/dist: No such
file or directory"; single-component dirs like `dist` happened to work.

Build the scan root by prepending `/` to the (host-validated, relative,
`..`-free) manifest dir instead. This matches the shape canonicalize
produced for single-component dirs and uses only plain wasi:filesystem
ops the preopen supports.

Adds an e2e fixture + test using a nested `dirs` entry, which reproduces
the failure without the fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lwshang lwshang requested a review from a team as a code owner June 7, 2026 13:57
@lwshang lwshang merged commit fb9d75c into main Jun 7, 2026
6 checks passed
@lwshang lwshang deleted the fix/wasi-canonicalize-nested-dir branch June 7, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant