Skip to content

fix: prevent ENOTDIR crash for non-component files in bundle directories @W-23924917@ - #1823

Open
WillieRuemmele wants to merge 2 commits into
mainfrom
wr/fix-enotdir-bundle-noncomponent-file
Open

fix: prevent ENOTDIR crash for non-component files in bundle directories @W-23924917@#1823
WillieRuemmele wants to merge 2 commits into
mainfrom
wr/fix-enotdir-bundle-noncomponent-file

Conversation

@WillieRuemmele

@WillieRuemmele WillieRuemmele commented Aug 19, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes forcedotcom/cli#3627 / @W-23924917@
  • sf project retrieve start --metadata and sf project deploy start --metadata crash with ENOTDIR when a non-component file (e.g., README.md, .DS_Store) sits directly inside a bundle type directory like lwc/, even if the file is in .forceignore
  • Three complementary guards prevent the crash without affecting resolution of valid bundle components

What changed

  1. MixedContentSourceAdapter.getRootMetadataXmlPath — checks isDirectory(componentRoot) before calling tree.find(), preventing the direct crash site from being reached
  2. BundleSourceAdapter.populate — when trigger is a file with no resolved component, checks whether trimPathToContent resolves to a directory; if not (file is at type-dir level, not inside a component folder), returns undefined
  3. NodeFSTreeContainer.readDirectory — defense-in-depth: returns [] for non-directory paths instead of letting readdirSync throw ENOTDIR

Why this is safe

  • For valid files inside component bundles (e.g., lwc/myCmp/helper.js), trimPathToContent returns the component folder which IS a directory — guards pass, resolution continues normally
  • UiWidgetBundle and DigitalExperience are unaffected because their content files are nested inside component folders (2+ levels below the type dir)
  • The readDirectory guard matches VirtualTreeContainer's existing behavior (which already threw on non-directory paths)

Test plan

  • New unit tests for BundleSourceAdapter — non-component files (README.md, .DS_Store) return undefined, valid components still resolve
  • New unit test for MetadataResolver.getComponentsFromPath — end-to-end: README.md in lwc/ returns empty array
  • New unit test for NodeFSTreeContainer.readDirectory — returns [] for file paths
  • All 439 resolve tests pass
  • Full test suite: 30,469 passing (3 pre-existing failures unrelated to this change)

…ype directories (W-23924917)

When a non-component file (e.g., README.md, .DS_Store) sits directly
inside a bundle type directory like lwc/, retrieve/deploy commands crash
with ENOTDIR because the file path is passed to readDirectory().

Three complementary guards:
- MixedContentSourceAdapter.getRootMetadataXmlPath: check isDirectory
  before calling tree.find() on the computed component root
- BundleSourceAdapter.populate: skip files whose trimPathToContent
  resolves to a non-directory (i.e., files at the type directory level
  rather than inside a component folder)
- NodeFSTreeContainer.readDirectory: return [] for non-directory paths
  instead of letting readdirSync throw ENOTDIR
@WillieRuemmele WillieRuemmele changed the title fix: prevent ENOTDIR crash for non-component files in bundle directories fix: prevent ENOTDIR crash for non-component files in bundle directories @W-23924917@ Aug 19, 2026
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.

sf project retrieve/deploy --metadata crashes ENOTDIR when a non-component file is in lwc/ (.forceignore ignored on this path)

2 participants