Title: vfs: MemoryProvider allows renaming a directory into its own descendant · Issue #64284 · nodejs/node · GitHub
Open Graph Title: vfs: MemoryProvider allows renaming a directory into its own descendant · Issue #64284 · nodejs/node
X Title: vfs: MemoryProvider allows renaming a directory into its own descendant · Issue #64284 · nodejs/node
Description: Version main Platform macOS 26.5.0 Subsystem vfs What steps will reproduce the bug? import vfs from 'node:vfs'; const fs = vfs.create({ emitExperimentalWarning: false }); fs.mkdirSync('/a/b', { recursive: true }); fs.writeFileSync('/a/fi...
Open Graph Description: Version main Platform macOS 26.5.0 Subsystem vfs What steps will reproduce the bug? import vfs from 'node:vfs'; const fs = vfs.create({ emitExperimentalWarning: false }); fs.mkdirSync('/a/b', { rec...
X Description: Version main Platform macOS 26.5.0 Subsystem vfs What steps will reproduce the bug? import vfs from 'node:vfs'; const fs = vfs.create({ emitExperimentalWarning: false }); fs.mkdirSync('...
Opengraph URL: https://github.com/nodejs/node/issues/64284
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"vfs: MemoryProvider allows renaming a directory into its own descendant","articleBody":"### Version\n\nmain\n\n### Platform\n\n```text\nmacOS 26.5.0\n```\n\n### Subsystem\n\nvfs\n\n### What steps will reproduce the bug?\n\n```js\nimport vfs from 'node:vfs';\n\nconst fs = vfs.create({ emitExperimentalWarning: false });\n\nfs.mkdirSync('/a/b', { recursive: true });\nfs.writeFileSync('/a/file.txt', 'data');\n\ntry {\n fs.renameSync('/a', '/a/b/c');\n console.log('rename succeeded');\n} catch (err) {\n console.log('rename threw:', err.code);\n}\n\nconsole.log('/ entries:', fs.readdirSync('/'));\nconsole.log('/a exists:', fs.existsSync('/a'));\nconsole.log('/a/b/c exists:', fs.existsSync('/a/b/c'));\n```\n\n### How often does it reproduce? Is there a required condition?\n\nAlways\n\n### What is the expected behavior? Why is that the expected behavior?\n\nThe rename should throw, typically `EINVAL`, and the tree should remain unchanged. A directory cannot be moved into its own descendant because that would create a cycle or orphan the directory hierarchy.\n\n### What do you see instead?\n\n```console\nrename succeeded\n/ entries: []\n/a exists: false\n/a/b/c exists: false\n```\n\nThe implementation moves `/a` into one of its own children, then removes the original root entry, detaching the whole subtree.\n\n### Additional information\n\n```js\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nconst dir = fs.mkdtempSync(path.join(os.tmpdir(), 'native-rename-'));\n\ntry {\n fs.mkdirSync(path.join(dir, 'a/b'), { recursive: true });\n fs.writeFileSync(path.join(dir, 'a/file.txt'), 'data');\n\n try {\n fs.renameSync(path.join(dir, 'a'), path.join(dir, 'a/b/c'));\n console.log('rename succeeded');\n } catch (err) {\n console.log('rename threw:', err.code);\n }\n\n console.log('root entries:', fs.readdirSync(dir));\n console.log('a exists:', fs.existsSync(path.join(dir, 'a')));\n console.log('a/b/c exists:', fs.existsSync(path.join(dir, 'a/b/c')));\n} finally {\n fs.rmSync(dir, { recursive: true, force: true });\n}\n```\n\nOutput\n```console\nrename threw: EINVAL\nroot entries: [ 'a' ]\na exists: true\na/b/c exists: false\n```","author":{"url":"https://github.com/trivikr","@type":"Person","name":"trivikr"},"datePublished":"2026-07-04T13:58:39.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/64284/node/issues/64284"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:2898df9b-5410-65f4-0c29-beefee86453e |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | AD38:291B8A:1B07B:24707:6A4D51FD |
| html-safe-nonce | 41fd055d4b04581c55ed5bead5c584f298d2ebb898adc1ecf620c5ad40a88670 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBRDM4OjI5MUI4QToxQjA3QjoyNDcwNzo2QTRENTFGRCIsInZpc2l0b3JfaWQiOiIyODI3MTQxNzE1OTA2NjEzNzU3IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | ef2ef764f13d0cd87f948551aa05a95edb911575f35b3fa1791bc9885e8cbe09 |
| hovercard-subject-tag | issue:4809240370 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/nodejs/node/64284/issue_layout |
| twitter:image | https://opengraph.githubassets.com/289a806f668cc591fdb83befa4510f1cf7264fff5cc911d12d6be5e62f887684/nodejs/node/issues/64284 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/289a806f668cc591fdb83befa4510f1cf7264fff5cc911d12d6be5e62f887684/nodejs/node/issues/64284 |
| og:image:alt | Version main Platform macOS 26.5.0 Subsystem vfs What steps will reproduce the bug? import vfs from 'node:vfs'; const fs = vfs.create({ emitExperimentalWarning: false }); fs.mkdirSync('/a/b', { rec... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | trivikr |
| hostname | github.com |
| expected-hostname | github.com |
| None | 92571a8944142227b7e19cd10918b1ddd06e5066c1ad5bc7e4769cf6140a87e6 |
| turbo-cache-control | no-preview |
| go-import | github.com/nodejs/node git https://github.com/nodejs/node.git |
| octolytics-dimension-user_id | 9950313 |
| octolytics-dimension-user_login | nodejs |
| octolytics-dimension-repository_id | 27193779 |
| octolytics-dimension-repository_nwo | nodejs/node |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 27193779 |
| octolytics-dimension-repository_network_root_nwo | nodejs/node |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 56fc8347865a14e2ec811533d68f929cf4e0ec19 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width