Skip to content

feat: throw ENOTDIR when reading files with trailing slash#1150

Merged
streamich merged 2 commits into
masterfrom
copilot/fix-1051
Aug 1, 2025
Merged

feat: throw ENOTDIR when reading files with trailing slash#1150
streamich merged 2 commits into
masterfrom
copilot/fix-1051

Conversation

Copilot AI commented Aug 1, 2025

Copy link
Copy Markdown
Contributor

This change makes memfs behavior consistent with Node.js on Linux by throwing ENOTDIR when attempting to read a file using a path with a trailing slash.

Problem

Previously, memfs would successfully read a file even when accessed with a trailing slash:

const { fs } = require('memfs');
fs.writeFileSync('/foo', 'hello');
console.log(fs.readFileSync('/foo/', 'utf8')); // Returns 'hello' (incorrect)

However, native Node.js on Linux throws an ENOTDIR error in this case:

const fs = require('node:fs');
fs.writeFileSync('/foo', 'hello');
console.log(fs.readFileSync('/foo/', 'utf8')); // Throws ENOTDIR (correct)

Solution

Modified the _readfile method in src/node/volume.ts to:

  1. Detect when the original path has a trailing slash before normalization
  2. Check if the resolved path points to a file (not a directory)
  3. Throw ENOTDIR error when trying to read a file with a trailing slash

The fix preserves existing behavior for directories and handles edge cases like symlinks, multiple trailing slashes, and the root path correctly.

Testing

Added comprehensive test cases covering:

  • Files with and without trailing slashes
  • Directories with and without trailing slashes
  • Symlinks to files with trailing slashes
  • Edge cases like root path and multiple slashes

All existing tests continue to pass, ensuring backward compatibility.

Fixes #1051.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI changed the title [WIP] Paths with trailing slashes should be treated as directories feat: throw ENOTDIR when reading files with trailing slash Aug 1, 2025
Copilot AI requested a review from streamich August 1, 2025 21:34
@streamich streamich marked this pull request as ready for review August 1, 2025 21:43
Comment on lines +61 to +65
// Root path without trailing slash should throw EISDIR
expect(() => fs.readFileSync('/', 'utf8')).toThrow(/EISDIR/);

// Root path with trailing slash should also throw EISDIR
expect(() => fs.readFileSync('/', 'utf8')).toThrow(/EISDIR/);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

?

@streamich streamich merged commit 5e8c264 into master Aug 1, 2025
20 checks passed
@streamich streamich deleted the copilot/fix-1051 branch August 1, 2025 21:54
@github-actions

github-actions Bot commented Aug 1, 2025

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 4.34.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Paths with trailing slashes should be treated as directories

2 participants