Version
main
Platform
Subsystem
vfs
What steps will reproduce the bug?
importvfsfrom'node:vfs';constfs=vfs.create({emitExperimentalWarning: false});fs.mkdirSync('/a/b',{recursive: true});fs.writeFileSync('/a/file.txt','data');try{fs.renameSync('/a','/a/b/c');console.log('rename succeeded');}catch(err){console.log('rename threw:',err.code);}console.log('/ entries:',fs.readdirSync('/'));console.log('/a exists:',fs.existsSync('/a'));console.log('/a/b/c exists:',fs.existsSync('/a/b/c'));How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
The 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.
What do you see instead?
rename succeeded/ entries: []/a exists: false/a/b/c exists: false
The implementation moves /a into one of its own children, then removes the original root entry, detaching the whole subtree.
Additional information
importfsfrom'node:fs';importosfrom'node:os';importpathfrom'node:path';constdir=fs.mkdtempSync(path.join(os.tmpdir(),'native-rename-'));try{fs.mkdirSync(path.join(dir,'a/b'),{recursive: true});fs.writeFileSync(path.join(dir,'a/file.txt'),'data');try{fs.renameSync(path.join(dir,'a'),path.join(dir,'a/b/c'));console.log('rename succeeded');}catch(err){console.log('rename threw:',err.code);}console.log('root entries:',fs.readdirSync(dir));console.log('a exists:',fs.existsSync(path.join(dir,'a')));console.log('a/b/c exists:',fs.existsSync(path.join(dir,'a/b/c')));}finally{fs.rmSync(dir,{recursive: true,force: true});}Output
rename threw: EINVALroot entries: [ 'a' ]a exists: truea/b/c exists: false
Version
main
Platform
Subsystem
vfs
What steps will reproduce the bug?
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
The 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.What do you see instead?
The implementation moves
/ainto one of its own children, then removes the original root entry, detaching the whole subtree.Additional information
Output