Repository navigation
Windows: opening a file preview locks its parent directory (and all ancestors) against rename/delete #11527
Replies: 1 comment
|
Follow-up: the same Windows lock also happens for directory targets, not only for file previews Additional measurements on the same machine (dsh 0.2.1-rc.2, Windows 11, NTFS). Directory targets are affected tooOpening a folder in the UI (file tree / directory view) locks that folder the same way:
Root cause is the other branch of the same functionIn const directory = (await this.stat(target, signal))?.type === "directory";
const root = directory ? path : dirname(path);
const watcher = watch(root, { ignoreInitial: true, depth: 0, ... });For a directory target So the fix needs to cover both branches: file target (watch of the parent directory) and directory target (watch of the directory itself). Verified local workaroundReplacing both branches with polling in a local plugin patch:
Result with the patch: preview open → zero handles under the affected subtree; the folder and all its ancestors can be renamed/deleted; the UI still refreshes the open preview and the directory listing within ~1 s. |
Uh oh!
There was an error while loading. Please reload this page.
[Windows] Opening a file preview locks its parent directory (and every ancestor) against rename/delete
Environment
webworkspace-write(ACL confinement active)Summary
While a file is open in the Web UI file viewer, the folder that contains the file — and every ancestor of that folder — cannot be renamed or deleted from Explorer. Explorer reports "You need administrator permission to delete this folder", but the DACL grants
DELETEand the failure is not a permissions problem. Closing the preview restores normal behavior immediately. This is Windows-specific.Steps to reproduce
D:\dsh\DSHWorkspace, and create校准\dirA\新建 文本文档.mdinside it.dirAsucceeds;校准fails with the "needs administrator permission" dialog.校准can be renamed/deleted again.Evidence
While the preview is open,
handle64(Sysinternals) reports twoFilehandles owned by the dsh host process on the parent folder of the opened file:Renaming the parent folder by
MoveFileW:MoveFileW(校准 → 校准-T)FALSE,GetLastError() = 5(ERROR_ACCESS_DENIED)TRUE, error0The same test on
dirAitself (the folder holding the opened file) succeeds in both states.DELETEaccess checks on校准pass in both states, and the ACL is unchanged — the sandbox'sDeny Everyone FILE_DELETE_CHILDACE is present but is not the cause.Root cause
@deepseek-ai/dsh-fs-local,LocalFileSystem#watch(lib/index.js):The Web file-resource follower (
@deepseek-ai/dsh-api-workspace-files→workspaceFiles.changes) calls this with the opened file, so the watcher root becomes the file's parent directory. On Windows the watcher keeps a real directory handle open.Windows refuses to rename or delete a directory while any object in its subtree has an open handle — even when that handle was opened with
FILE_SHARE_DELETE— and returnsERROR_ACCESS_DENIED (5). Explorer renders that as the elevation prompt "You need administrator permission…", because deleting to the Recycle Bin is a whole-tree rename.Consequence: opening a preview locks the file's parent directory and, transitively, all of its ancestors — including the workspace root.
Related case (same class, different component)
@deepseek-ai/dsh-skill-filesystemwatches every skill root withwhich keeps handles on each skill directory (e.g.
.dsh/skills/<skill>) and, transitively, on.dsh/skills,.dshand the workspace root. While dsh runs, renaming/deleting a skill directory or its ancestors fails the same way. (Arguably expected for hot reload, but it has the same Windows side effect.)Suggested fix
fs.watchFile(stat polling) is the simplest; the cost is a refresh latency of one poll interval.usePollingfor file followers and for skill roots.Workaround (no code change)
Rename/move/delete the ancestor after closing the preview, or delete recursively (
Remove-Item -Recurse,rd /s /q) which deletes item by item instead of renaming the whole tree.All reactions