DeepSeek Harness WSL UNC: write fails with EIO Win32 1
A DeepSeek Harness workspace that can read, list, and search but never write is not a permissions problem; admission and the file backend disagree about what "supported filesystem" means. Admission checks only path spelling, so UNC passes; writes assume NTFS semantics, and GetFileSecurityW returns ERROR_INVALID_FUNCTION on the 9P share, surfaced as EIO (Win32 1). According to the discussion, the reporter reproduced this in the desktop app, and community members reviewed the workspace and fs-local sources (discussion).
Read, write, and terminal each report differently in a DeepSeek Harness UNC workspace
The same workspace behaves differently across four kinds of operations; record them by operation before deciding whether this is admission or backend capability.
- Open
\\wsl.localhost\Ubuntu\home\you\projas a workspace in the desktop app. Expected: it loads. - Ask the model to edit an existing file. Expected:
Error: GetFileSecurityW EIO (Win32 1): \\wsl.localhost\... - Ask the model to create a file. Expected:
FS_IO_ERRORwithcannot writein the message, and the code is notENOTSUP. - Open a terminal tab in the workspace. Expected: it lands in
cmd.exeand reports that UNC paths are not supported, then gives up the current directory. - Read an ordinary file and list a directory. Expected: both succeed. Time one
statwithMeasure-Command; expected about 17,000 microseconds per file versus about 86 microseconds inside WSL. - Access a symlink such as
/etc/os-releaseor/lib. Expected:ENOENT, because the share exposes Linux symlinks as reparse points Windows cannot resolve.
A successful read does not mean the workspace is usable; it only means the 9P read path is sufficient.
Why admission lets UNC through: it only rejects two root forms
The check is meant to reject relative drive paths and root-relative paths; UNC is simply not on its rejection list, which is not the same as being supported. The predicate reviewed by the community is:
if (platform !== 'win32') return posix.isAbsolute(path)
const root = win32.parse(path).root
return win32.isAbsolute(path) && root !== '\\' && root !== '/'
For \\wsl.localhost\Ubuntu\home\you\proj, win32.parse(path).root is \\wsl.localhost\Ubuntu\, which matches neither rejected form, so the guard passes. Only realpathNormalize runs afterward; there is no filesystem capability check. Admission and the backend share no information about what the volume supports, so failure can only appear at the first operation.
Why writes must fail: GetFileSecurityW has no 9P equivalent
Publishing a file on Windows copies the source DACL and then replaces the target; both steps assume security descriptors work, and 9P provides neither. The same DACL failure also shows up in Windows sandbox commands, covered in Windows ACL sandbox command failures. The chain:
fs-local/src/win32.ts:92-97callsGetFileSecurityW(nativePath, DACL_SECURITY_INFORMATION, ...).- When it returns 0, the code throws
win32Error('GetFileSecurityW', api.getLastError(), path), and 9P supplies error code 1. - Lines
:122-132of the same file publish throughReplaceFileW, which is also not a 9P primitive. - Creating a new file goes through the
link(temp, dest)guard; 9P rejects hard links withENOTSUP, but the fs layer wraps it as a genericFS_IO_ERRORand leaves the errno only in the message text. - Conclusion: DACL-copy publishing is meaningless on this kind of share. This is not a missing row in a mapping table.
Path 1: reject UNC at DeepSeek Harness admission
The most honest fix is to say "unsupported" at adoption time, so users learn the path is a dead end before they see EIO. Steps:
- Add a root check to the win32 branch of
paths.ts: treatroot.startsWith('\\\\')as UNC. Expected: the predicate rejects UNC roots as unsupported. - Return an explicit "unsupported workspace type" error on a match, rather than returning
falseand silently falling into another branch. Expected: the caller receives an explicit error instead of a silent fallback. - Cover four spellings,
\\wsl.localhost\,\\wsl$\,\\?\UNC\, and\\server\share\; add each as a workspace. Expected: all four are rejected. - Regression-test an NTFS drive path. Expected: adding and read/write behavior are unchanged.
Accept the cost: UNC workspaces that currently read and list will be rejected too, including intentional network shares.
Path 2: keep DeepSeek Harness admission, fail the first write with a capability error
If you do not want to remove the existing read-only use, keep admission but move the failure to the first write and describe it as "this filesystem is unsupported" rather than "an API failed". Steps:
- Probe the target volume's capability at the write entry point, or recognize error code 1 from
GetFileSecurityWas "unsupported". Expected: the write path knows whether the volume supports DACL calls before it starts. - Throw an error that names the filesystem type, for example "UNC/9P workspaces do not support DACL-copy publishing; use a drive letter or run inside WSL". Expected: the message names the filesystem and a workable alternative.
- Add a persistent notice to these workspaces saying they are read-only. Expected: the workspace shows a read-only notice in the UI.
- Retest: reads, listings, and search remain available; writes fail immediately with readable text. Expected: reads still work and writes fail with the new message.
- Include the 17,000-microsecond
statcost in the notice so users do not wait on large directories. Expected: the notice explains the per-file latency cost. - Store a "read-only workspace" flag in the workspace record so the notice survives a restart instead of depending on session memory. Expected: the notice reappears after restart.
Path 3: map a drive letter and retest DeepSeek Harness DACL copy
A drive mapping solves "admission does not recognize it" and "cmd.exe does not accept UNC", but the share underneath is still 9P, so write support must be tested rather than assumed. Steps:
- Confirm the WSL distribution is running:
wsl -l -v. Expected: state isRunning. - Run
net use W: \\wsl.localhost\Ubuntu\home\you\proj /persistent:yes. Expected: the command completes successfully. - Add
W:\as a workspace. Expected: admission passes because the root is now a drive root. - Edit an existing file. Expected one of two outcomes: it succeeds, meaning DACL calls work through this mapping; or it still fails with
EIO (Win32 1), meaning the underlying semantics did not change, so return to Path 1 or Path 2. - Create a new file. Expected: no more
FS_IO_ERROR; anENOTSUPstill means hard links are unavailable. - Open a terminal on
W:\. Expected: no UNC-unsupported message. - Run
net use W: /deleteand reopen the workspace. Expected: a clear error rather than a directory that quietly stops working.
A drive mapping is not a master key: it bypasses path-spelling checks, not filesystem capability.
How to choose in DeepSeek Harness: does the workspace need writes?
The three paths divide on one question: will this workspace be written to?
| Your need | Choose | Outcome |
|---|---|---|
| Read-only browsing of a WSL project | Path 2 | Keep current behavior and readable errors |
| Writes required, host can change | Path 1 plus run inside WSL | Rejected at adoption, no false expectation |
| Writes required, Windows tools needed | Path 3 | Map a drive, then test writes |
| A uniform team environment | Path 1 | No wrong expectation from the start |
| A one-off file edit | Path 3 | Map, then run a write test first |
One last note: a DSH plugin such as dsh-plugin-wsl-env uses a resident agent that takes over files and shell, but that is not a built-in host capability, so upgrades and compatibility are your responsibility (per the discussion).
Whichever path you choose, ask "does this workspace support writes?" before adoption. That is much cheaper than discovering EIO on the first edit.
Source: Discussion #10260.
FAQ
DeepSeek Harness writes go through the Windows DACL copy path, and GetFileSecurityW returns ERROR_INVALID_FUNCTION (Win32 1) on a 9P share, which the upper layer reports as EIO. Reads never take that path, so reading and listing look completely normal.
DeepSeek Harness admission only checks that the path is absolute and that its root is not a backslash or a slash. The root of \\wsl.localhost\Ubuntu\ is neither, so the guard passes. Passing means 'not one of the two rejected forms', not 'this filesystem is supported'.
In DeepSeek Harness, mapping the WSL directory to a drive letter bypasses admission and the terminal's UNC restriction, not necessarily the backend. The drive still points at the same 9P share, so whether GetFileSecurityW and ReplaceFileW work depends on the underlying implementation. Retest writes after mapping.
Yes — DeepSeek Harness can run inside WSL so the workspace is a local Linux path, or you can use the third-party plugin dsh-plugin-wsl-env mentioned in the discussion, where a resident agent takes over file and shell access.
Related Terms
- UNC path
- A UNC path is a network resource path beginning with two backslashes, such as `\\server\share\dir`, with no drive letter. It is resolved by the network redirector, and its capabilities depend on which filesystem operations the server implements.— https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
- 9P
- 9P is the sharing protocol WSL uses to expose Linux filesystems to Windows; both `\\wsl.localhost` and `\\wsl$` go through it. It provides basic file operations and does not implement Windows security descriptor calls.— https://github.com/deepseek-ai/deepseek-harness/discussions/10260
- ERROR_INVALID_FUNCTION
- ERROR_INVALID_FUNCTION is Win32 error code 1, meaning the target object does not support the requested function. On a 9P share it is returned by `GetFileSecurityW` and displayed as `EIO (Win32 1)`.— https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
- GetFileSecurityW
- GetFileSecurityW is the Win32 API that reads an object's security descriptor; fs-local uses it on Windows to copy the source file's DACL when publishing. Only filesystems that store security descriptors return it normally.— https://learn.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-getfilesecurityw
Sources
- deepseek-harness Discussion #10260: workspace validation accepts WSL UNC paths, but the file toolchain cannot write· deepseek-ai (GitHub Discussions)
- deepseek-harness repository: review of workspace/src/paths.ts and fs-local/src/win32.ts· deepseek-ai (GitHub)