[hyperv] failed to mount Plan9 share "c": Plan9 mount failed: invalid argument
A Windows drive failed to attach to a Linux virtual machine, and everything
downstream inherited that failure. Nothing here reached the network: your API
key was never used, no tokens were counted, no request was sent. It is also not
a missing file and not a file-permission problem — the files are fine, sitting
on a disk that the guest cannot currently see at all. The share named "c" is
your C: drive, and the message says the attempt to attach it was rejected.
Plan 9 is the door between the two operating systems
A WSL2 or Hyper-V guest is a real virtual machine with its own kernel. It has no
native access to your Windows disks; a path like /mnt/c is not a partition,
it is a network-style filesystem mounted over a share protocol. Plan 9 (9P)
is one of the protocols used for that job, virtiofs is the other, and neither is
something you installed or chose. They exist so a Linux process can open a file
that physically lives on the Windows side.
That is the whole reason this error is confusing: the message names a protocol you never picked, to describe a step you never knew was happening, and the symptom you actually see is a tool claiming your project directory is empty.
The consequence is worth stating flatly, because it saves an hour of the wrong investigation. Every file under the failed mount point is unreachable for the same single reason, so there is no point diagnosing individual files. A tool that reports one missing directory, then a different missing directory, then a config file it cannot read, is not experiencing three problems.
“Invalid argument” means the two sides disagreed, not that you lacked rights
invalid argument is the standard text for EINVAL: a system call was rejected
because the arguments handed to it were not acceptable. The mount was refused on
its terms — the share name, the protocol options, the transport parameters —
before anything asked who you were or what you were allowed to read. If the
guest had been refused for lack of privilege, the errno would have said
permission denied, and it does not.
That single distinction disposes of the most popular fix on the internet for
this message. Elevating the terminal, elevating the tool, or adding the user to
another group changes the answer to a question nobody asked. You will get the
identical EINVAL, now with more authority behind it.
It also tells you where to look. An argument-level rejection usually means the host is not offering that share under that name right now, or the two sides are no longer speaking the same dialect of the protocol — the classic cause of which is that one side changed underneath you.
Is retrying useful?
No, and more importantly, the thing most people do next is not a retry at all.
Re-running your command does not re-attempt the mount. The share is established as part of bringing the virtual machine up; by the time a tool runs inside the guest, that decision was made and failed. Launching the tool a second time executes against the same broken mount table and fails the same way, instantly.
The useful action that resembles a retry is restarting the virtualization subsystem itself, which tears the VM down and re-negotiates the share from scratch. Do it exactly once before you change any configuration — a mount table left in a bad state after a host component updated will often come back cleanly on a fresh boot. Microsoft documents the command that shuts the subsystem down; take its current form from their WSL documentation, not from a forum post.
If a clean restart produces the same EINVAL, stop restarting. You have just
proven the failure is deterministic, and the rest of this page is about it.
Telling a host-side regression from your own configuration
Each of these either indicts a component or clears it. Run them from a plain shell inside the guest, not from inside the coding tool — you want to know whether the mount works, not whether one program is confused.
Does anything else on the guest see the drive? List the mount point with a basic shell command. If it is empty or absent, the tool is reporting the truth and its configuration is not involved. If the drive is there and readable but the tool still cannot find your project, you have a different problem and this page is not it.
Did everything break at once? A share failure takes out every tool that touches the Windows filesystem — editors, build systems, language servers, the coding agent. Breakage confined to one program is not a mount failure.
Did anything inside the guest change? If you installed nothing, edited nothing, and it worked yesterday, the change was on the host. Host-side updates to the virtualization stack arrive on their own schedule and can change the terms of the share without any action from you; a regression of exactly this shape — everything mounting fine, then nothing mounting, with no guest-side change — is the signature.
Do other guests fail identically? If you have a second distribution or VM on the same host, start it. All guests broken means the host side owns the problem and you should stop editing anything inside this one. One guest broken means the fault is that guest’s configuration or state.
Fixes, keyed to the check that selected them
- Restart resolved it — you are done, but watch for a repeat. A share that needs a subsystem restart after every host reboot is a host-side regression stepped around rather than fixed. Note the date and what the host updated.
- All guests fail, nothing changed inside them — this is the host’s virtualization components, and the fix belongs there: bring the host’s virtualization and WSL components to a consistent state, or roll back the update that coincided with the breakage. Do not paste registry values, kernel parameters or config keys from a search result into this. The configuration surface for WSL file sharing is documented by Microsoft, it changes between releases, and a stale key applied to a current build is how a recoverable problem becomes an unrecoverable one. Take the names from the vendor’s current documentation.
- One guest fails, others are fine — that guest’s own state, not the host’s. Recreating it beats archaeology when the work inside is disposable.
- You need to keep working today — move the project onto the guest’s own
filesystem so no cross-OS share is involved in reading it. This is also the
better steady state for reasons unrelated to this error: Claude Code’s
documentation notes that searches spanning the WSL filesystem boundary return
fewer results than expected, and that
claude doctorstill reports Search as OK when they do. A boundary that degrades your tooling silently is not a good place to keep a repository.
Two shortcuts that cost more than they fix
Running the tool elevated. Beyond being aimed at the wrong errno, it is worth knowing what you would be spending. The guest exists so that commands run by an autonomous coding agent execute inside a machine that is not your machine, and the share is the deliberately narrow channel between the two. Raising the privilege of everything in that chain widens what a mistake on the other side can reach on your real disk, in exchange for nothing, because the mount is being rejected on its arguments.
Turning off the VM and running the agent directly on Windows. This does make the message disappear, in the sense that a problem cannot occur in a component you deleted. What it actually does is remove the containment: an agent that can create files, run build commands and execute shell commands now does so against your host directly. That may be an acceptable trade for a throwaway workspace with no credentials in it. It is not a debugging step, and it should never be the first thing you try for a mount error that a subsystem restart might have cleared.
There is a quieter version of the same mistake: creating an ordinary empty directory where the mount belongs, so the errors stop. They will stop. The tool will then report your project as empty and read nothing, and you will have removed the only signal that told you why.
How to confirm it’s fixed
Restart the virtualization subsystem cold — not a new terminal window, not a relaunched tool — and from a plain shell inside the guest, list the mount point and read the contents of a file whose contents you already know. Listing proves the directory resolves; reading proves data actually crosses the share. Do both twice, in separate sessions.
Then reboot the host once and repeat. A share that works until the next reboot was fixed by hand, not fixed, and you want to discover that now rather than during your next deadline. Only after those pass should you go back to the tool that originally complained.
Related errors
If your message arrives through an RPC layer and ends in bad address instead,
read
failed to ensure virtiofs mount: Plan9 mount failed: bad address
instead of this page — a different errno there means the failure is not a
configuration disagreement, and the advice diverges at that point.
The downstream symptom usually looks nothing like a mount problem. When a tool
reports
ENOENT on a path that clearly exists,
check whether that path lives under a share before you start creating
directories to satisfy it. If instead a program cannot be located rather than a
file,
spawn node ENOENT
is a PATH resolution failure and has nothing to do with mounts.
When you are not sure which layer you are on — host, share, guest filesystem, or the API — the AI coding error triage tool sorts errors by the signals used above: who printed the line, what errno it carries, and whether anything ever left your machine.