Skip to content

Fix copy:build ENOENT on extensionless README symlinks#146

Open
agibson-godaddy wants to merge 2 commits into
masterfrom
fix/copy-build-ENOENT
Open

Fix copy:build ENOENT on extensionless README symlinks#146
agibson-godaddy wants to merge 2 commits into
masterfrom
fix/copy-build-ENOENT

Conversation

@agibson-godaddy

@agibson-godaddy agibson-godaddy commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

The copy:build task fails with a misleading ENOENT: ... lstat 'README.md' error in any plugin whose dependency tree includes a vendored package with a relative-target README symlink (e.g. cybersource/rest-client-php pulls in singpolyma/openpgp-php, which ships README -> README.md).

The error

[13:06:47] Starting 'copy:build'...
[13:06:48] 'copy:build' errored after 474 ms
[13:06:48] Error: ENOENT: no such file or directory, lstat 'README.md'

The cause

vendor/singpolyma/openpgp-php/ contains an extensionless symlink:

README -> README.md

When gulp.src (via vinyl-fs) globs this file, it calls fs.readlink() to read the target (README.md) and then fs.lstat() on the bare target string. That lstat is resolved relative to the gulp cwd (the plugin root), not the symlink's directory — and README.md doesn't exist at the plugin root, so the task crashes.

The error message points at README.md because that's the readlink target, which is why it's a red herring: there's no actual README.md involved in the copy, and the failure isn't a race condition or task-ordering issue.

The fix

Exclude extensionless README files from the build glob alongside the existing readme.md exclusion. These are documentation files we don't ship anyway, and excluding them sidesteps vinyl-fs's broken handling of relative-target symlinks.

Test plan

  • In a plugin that depends (transitively or directly) on singpolyma/openpgp-php (e.g. cybersource gateway), run npx sake copy:build and confirm it completes without the ENOENT error
  • Confirm the build directory does not contain the extensionless README symlink
  • Confirm normal readme.md / readme.txt / README.md exclusions still behave as before

🤖 Generated with Claude Code

Copilot AI 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.

Pull request overview

Fixes copy:build failures caused by vendored packages that contain extensionless README symlinks pointing to relative targets (e.g., README -> README.md), which can trigger a misleading ENOENT ... lstat 'README.md' error during gulp.src globbing.

Changes:

  • Exclude extensionless README files from the build copy glob to avoid vinyl-fs’s incorrect relative-target symlink handling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

2 participants