Skip to content

fix(deploy): prune dangling standalone symlinks before rsync#38

Merged
setoelkahfi merged 2 commits into
developmentfrom
fix/nextjs-ssr-prune-dangling-symlinks
Jul 8, 2026
Merged

fix(deploy): prune dangling standalone symlinks before rsync#38
setoelkahfi merged 2 commits into
developmentfrom
fix/nextjs-ssr-prune-dangling-symlinks

Conversation

@setoelkahfi

@setoelkahfi setoelkahfi commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Fixes the nextjs-ssr deploy failing with rsync ... status 23 on pnpm monorepos.

What happens

The standalone upload runs rsync --copy-links, so rsync follows every symlink. On pnpm, Next's standalone tracing sometimes leaves a compat symlink pointing at a package version it never actually wrote into the bundle. A real one: .pnpm/node_modules/semver -> ../semver@6.3.1/node_modules/semver, when only semver@7.x got traced. The 6.3.1 target isn't there, so the link dangles. rsync tries to follow it, hits an IO error, and exits 23. The deploy aborts with an empty stderr, so the real cause is invisible from the CLI output.

The change

A new step 3b in process_deploy_nextjs_ssr runs between the build and the rsync. It walks .next/standalone/ and removes any symlink whose target is missing. It recurses into real directories but never follows a symlinked directory, so there's no risk of cycles. The dangling package was never part of the traced runtime, so deleting the link is safe. If it removes anything, it prints the count.

No new dependencies (std only). This does in the CLI what the skill used to tell people to do by hand (find ... -delete before deploy), so every pnpm monorepo gets it without a manual step.

Tests

Two unix-gated unit tests: one checks that a dangling link is removed while a valid link and real files survive, the other checks that a clean tree is left alone. The full crate suite passes (11 tests) and cargo check -p smbcloud-cli is clean.

I also updated the smbcloud-deploy-nextjs skill so the status-23 section says the CLI handles this now, with the manual find/postbuild step only needed on smb 0.4.7 and older.

The nextjs-ssr deploy uploads .next/standalone with `rsync --copy-links`, so
rsync follows every symlink. On pnpm monorepos, Next's standalone tracing can
leave a compat symlink pointing at a version it never wrote into the bundle,
like .pnpm/node_modules/semver -> ../semver@6.3.1/... when only semver@7.x was
traced. The link dangles, rsync fails trying to follow it, exits 23, and the
deploy aborts with an empty stderr.

Add a step 3b that walks .next/standalone after the build and deletes any
symlink whose target is missing, before the rsync runs. It recurses into real
directories but never follows a symlinked one, so there are no cycles. The
dangling package isn't part of the traced runtime, so removing the link is
safe. It prints how many it removed.

Replaces the manual find/delete workaround for every pnpm monorepo. The
smbcloud-deploy-nextjs skill is updated to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@setoelkahfi setoelkahfi force-pushed the fix/nextjs-ssr-prune-dangling-symlinks branch from f8f7409 to e894c6a Compare July 5, 2026 19:24
Review follow-ups on the dangling-symlink prune:

- Swap exists() for try_exists()? in both branches so a stat error on a
  symlink target propagates instead of being misread as "dangling" and
  deleting a link we merely failed to stat.
- Note in the docstring that the walk depends on pnpm's layout, where every
  package dir is a real directory reachable directly (so nested dangling
  links are always visited).
- Print the success symbol on the prune line to match the other step output.
- Add a cycle-safety test (a dir symlink pointing back at the root must not
  be followed) and a root-is-dangling-symlink test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@sigit-code sigit-code Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Adds a prune_dangling_symlinks helper to the nextjs-ssr deploy path that recursively walks .next/standalone/ removing symlinks whose targets are missing, run as a new step 3b before the rsync --copy-links upload. This fixes rsync exiting with status 23 on pnpm monorepos where Next's standalone tracing leaves dangling compat symlinks. Includes four unix-gated tests and a skill doc update. The core logic to verify is the try_exists handling and the non-following of directory symlinks.


Automated review by siGit Code · commit 907c9ca

Comment thread crates/cli/src/deploy/process_deploy_nextjs_ssr.rs
@setoelkahfi setoelkahfi merged commit 319ab8c into development Jul 8, 2026
6 checks passed
@setoelkahfi setoelkahfi deleted the fix/nextjs-ssr-prune-dangling-symlinks branch July 8, 2026 19:42
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