Skip to content

RPC error -1: failed to ensure virtiofs mount: Plan9 mount failed: bad address

A component asked another component to make a filesystem share available, and the answer came back as a failure. Nothing here involves your API key, your quota, or the model — no request left the machine. It is also not a missing file and not a file-permission problem: the files exist and you are allowed to read them, but the path between the virtual machine and the disk they live on was never established, so from inside the guest they do not exist at all.

Read this message from right to left

Three layers are stacked in one line, and only the rightmost one carries a diagnosis.

RPC error -1 is not an error code. -1 is the conventional “something failed” sentinel returned by a call with no more specific answer to give. There is no table to look it up in, and searching for it returns results from unrelated software that also returns -1. All it tells you is that the failure crossed a process boundary on its way to your screen.

That boundary matters for a practical reason: the program that printed this line is not the program that attempted the mount. Its logs will contain this message and nothing else useful. The component that actually tried, and knows why it failed, is on the other side of the call.

failed to ensure virtiofs mount is reconciliation language. “Ensure” means the caller asked for a state — this share should be mounted — rather than for an action. That kind of call is usually made repeatedly and idempotently, every time a sandboxed workspace or a VM-backed session starts. So this error does not necessarily mean something was just built and failed; it commonly means something that was working is now being re-established and cannot be.

The two protocol names are the most useful part

virtiofs and Plan 9 (9P) are two different protocols for handing a host’s files to a guest virtual machine. A WSL or Hyper-V guest has no native access to your Windows disks; a path under the guest that maps to a Windows drive is a share served over one of these, not a partition.

The message names both because the request was for virtiofs and the failure came back from a Plan 9 mount attempt. That is a fallback in progress: the environment could not satisfy the preferred protocol and dropped to the older one, which then failed as well.

That single observation kills the fix most readers reach for. Having read that virtiofs is newer and faster, or that it is less mature, the obvious move is to force the other protocol. There is nothing to switch to. Both paths have already been tried within this one error, and the second one is the one that produced the errno you are reading.

“Bad address” is not a configuration disagreement

bad address is the standard text for EFAULT: a memory address handed to a system call was not valid in the caller’s address space. It is a fault in the mechanics of the call itself, not a rejection of what you asked for.

This is the line that separates this page from its neighbour. When a share is refused because the two sides disagree about the share name, the options or the terms, the errno is invalid argument, and looking at configuration is the right response. EFAULT is different in kind. A buffer crossing the boundary was not where the receiving side expected it to be, and there is no setting you own that determines that. Hours spent editing configuration for an EFAULT are hours spent on a hypothesis the errno already contradicted.

What does produce it, realistically, is the two sides of that boundary not belonging together — a host virtualization component updated independently of the guest kernel or the guest-side service, a partially completed update, or a genuine defect in one of them. That is why the fixes below are about reconciling versions and restarting cleanly, and why “report it with the exact string” is a legitimate outcome here rather than a way of giving up.

Is retrying useful?

No — and the retry you are considering has already happened.

An “ensure” call is by design something that can be made over and over. If a workspace manager runs it at session start, then closing your tool and opening it again is not a new experiment; it is the same reconciliation running a second time against an unchanged environment, and it will fail the same way in the same number of milliseconds.

There is one restart that is genuinely different, and it is worth exactly one attempt: a cold restart of the virtualization subsystem, and then of the host machine. That forces both sides of the boundary to re-handshake from scratch, which is the only thing in the retry family that changes an input. A partially applied host update very often clears at that point. Microsoft documents the command that shuts the WSL subsystem down; take its current form from their documentation.

If a cold restart of both machines reproduces the error, stop restarting. You have established that the failure is deterministic, which is the useful finding, and every further attempt costs you time to learn nothing.

Narrowing down which component is broken

Run these from a plain shell in the guest and from the host, not from inside the coding tool. You are testing whether sharing works, not whether one program is confused.

Do ordinary shares work while the managed one fails? This is the highest value test on the page. Open a normal guest shell and read a file from a Windows drive mount. If that works while a sandboxed or VM-backed workspace still fails to ensure its mount, general file sharing on this machine is healthy and the fault belongs to the service that manages that workspace. Stop debugging WSL.

Does the mount point exist but reading from it fail? A directory that resolves but faults on read is a half-established mount, and it is why a tool can report a path as present in one operation and missing in the next. Treat the mount as absent regardless of what the directory listing suggests.

Did the host update recently? Virtualization components on the host update on their own schedule. If nothing inside the guest changed and this started on its own, version skew is the leading hypothesis rather than a guess.

Does a second guest behave the same way? All guests failing points at the host. One guest failing points at that guest’s kernel or its guest-side service.

Fixes, safest first, with what each costs

  • Cold restart of subsystem and host — free, and it resolves the partially applied update case outright. Do this before anything else.
  • Bring both sides to a consistent, current state — update the host’s virtualization and WSL components, and the guest’s kernel and guest-side services, together rather than one at a time. Do not apply registry values, kernel parameters or config keys copied from a search result. Those keys change between releases, none of them are documented as a remedy for EFAULT, and a stale one applied to a current build turns a recoverable problem into an unbootable guest. Take names and values only from the vendor’s current documentation.
  • Work inside the guest’s own filesystem — a project on the guest’s own disk needs no cross-OS share, so this error cannot occur on that path. Claude Code’s documentation gives an independent reason to prefer it: searches spanning the WSL filesystem boundary return fewer results than expected, and claude doctor still reports Search as OK when they do.
  • Report it — with the full string, both sides’ versions, whether ordinary shares work at the same moment, and whether a cold restart of both machines changes anything. EFAULT across a version boundary is the kind of thing that gets fixed in the component, not in your configuration, and a report with those four facts is actionable. Without them it is a description of a feeling.

The shortcut to refuse

The suggestion you will find fastest is to disable the sandbox or the VM-backed workspace and let the agent work on the host directly. It does make the message stop, because a mount that is never attempted cannot fail.

Understand what you would be spending. The guest is what keeps commands run by an autonomous coding agent from executing against your actual machine, and the share is the narrow, deliberate channel between them. Removing the guest does not repair the channel; it removes the wall the channel went through. For a throwaway workspace holding no credentials that can be a defensible choice made on purpose — but it is not a diagnostic step, and reaching for it before a cold restart trades a real security property for something a reboot might have given you free.

The same goes for running the tool elevated: nothing in this failure asked who you were, so elevation buys the identical error at the price of a wider blast radius on your host disk.

How to confirm it’s fixed

From a plain shell inside the guest, list the mount point and read a file whose contents you already know. Listing only proves a directory resolved; reading proves bytes actually crossed the boundary, which is exactly what a half-established mount fails to do.

Then restart the host, repeat that, and start the workspace that originally failed so it runs its own ensure step. Three conditions have to hold together: a plain shell reads through the share, the managed workspace starts clean, and both still hold after a reboot. A fix that survives only until the next boot was applied by hand to a running system and will be back.

If your message ends in invalid argument rather than bad address, you are on the other branch of this fork and the advice differs: read Plan9 mount failed: invalid argument, where the mount was rejected on its terms and reconciling what the host offers is the productive move.

Downstream, a failed share does not announce itself. A tool reporting ENOENT on a path that plainly exists is the usual first symptom, and creating the directory to satisfy it makes things worse rather than better. If a program rather than a file cannot be found, spawn node ENOENT is PATH resolution and unrelated to mounts.

To work out which layer you are on before spending time on any of them, the AI coding error triage tool sorts by the same signals used above: which component printed the line, what errno it carries, and whether anything ever left the machine.