xpipe-io/xpipe · error · BeaconClientException

Directory " + msg.getPath().getParent() + " does not exist

Error message

Directory " + msg.getPath().getParent() + " does not exist

What it means

Before writing, FsWriteExchange verifies that the parent directory of the target path exists on the remote filesystem via fs.directoryExists(). The daemon does not implicitly create directories, so writes into missing directories are rejected.

Source

Thrown at app/src/main/java/io/xpipe/app/beacon/api/FsWriteExchange.java:37

public class FsWriteExchange extends BeaconInterface<FsWriteExchange.Request> {

    @Override
    public String getPath() {
        return "/fs/write";
    }

    @Override
    @SneakyThrows
    public Object handle(HttpExchange exchange, Request msg) {
        var shell = AppBeaconServer.get().getCache().getShellSession(msg.getStore());
        var fs = new ShellFileSystem(shell.getControl());

        if (!msg.getPath().isAbsolute()) {
            throw new BeaconClientException("File path " + msg.getPath() + " is not absolute");
        }

        if (!fs.directoryExists(msg.getPath().getParent())) {
            throw new BeaconClientException("Directory " + msg.getPath().getParent() + " does not exist");
        }

        try (var in = BlobManager.get().getBlob(msg.getBlob());
                var os = fs.openOutput(msg.getPath(), BlobManager.get().getSize(msg.getBlob()))) {
            in.transferTo(os);
        }
        return Response.builder().build();
    }

    @Jacksonized
    @Builder
    @Value
    public static class Request {
        @NonNull
        UUID store;

        @NonNull
        UUID blob;

View on GitHub (pinned to d85ca821ba)

Solutions

  1. Create the parent directory first (shell command mkdir -p or a directory-creation API call) then retry the write
  2. Choose a target path inside an existing directory
  3. Verify the parent path spelling and that mounts are active on the host
  4. Use the parent-existence check client-side before uploading

Example fix

// before
client.writeFile(store, Path.of("/opt/app/config.yaml"), blob);
// after
Path target = Path.of("/opt/app/config.yaml");
client.mkdir(store, target.getParent());
client.writeFile(store, target, blob);
Defensive patterns

Strategy: validation

Validate before calling

if (!client.directoryExists(store, target.getParent())) {
    client.mkdir(store, target.getParent());
}

Try / catch

try {
    client.writeFile(store, target, blob);
} catch (BeaconClientException e) {
    if (e.getMessage().startsWith("Directory ") && e.getMessage().endsWith("does not exist")) {
        client.mkdir(store, target.getParent());
        client.writeFile(store, target, blob);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling the fs write endpoint when msg.getPath().getParent() does not exist on the target store — e.g. writing to /opt/app/config.yaml before /opt/app exists, or after the directory was removed.

Common situations: First deployment to a fresh host where the app directory hasn't been created; typos in the parent directory; mounts not yet mounted when the write runs; Windows drive/path mismatches.

Related errors


AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06). Data as JSON: /api/errors/54e41ad3d3703ea6. Report an issue: GitHub.