xpipe-io/xpipe · error · BeaconClientException

File path " + msg.getPath() + " is not absolute

Error message

File path " + msg.getPath() + " is not absolute

What it means

FsWriteExchange requires an absolute target path for the file being written. A relative path cannot be resolved reliably on the remote shell filesystem, so the daemon rejects the request before performing any I/O.

Source

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

import lombok.extern.jackson.Jacksonized;

import java.util.UUID;

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

View on GitHub (pinned to d85ca821ba)

Solutions

  1. Resolve the path to absolute on the client before calling (baseDir.resolve(name).normalize())
  2. Anchor writes to a known absolute directory on the remote host
  3. Validate path.isAbsolute() client-side and fail early with a clearer message
  4. For Windows targets, include the drive letter (e.g. 'C:\\temp\\out.bin')

Example fix

// before
client.writeFile(store, Path.of("out.bin"), blob);
// after
Path target = remoteBaseDir.resolve("out.bin").normalize();
if (!target.isAbsolute()) throw new IllegalArgumentException("target must be absolute");
client.writeFile(store, target, blob);
Defensive patterns

Strategy: validation

Validate before calling

Path target = baseDir.resolve(name).normalize();
if (!target.isAbsolute()) {
    throw new IllegalArgumentException("Write target must be absolute: " + target);
}

Type guard

boolean isAbsoluteWriteTarget(Path p) {
    return p != null && p.isAbsolute() && p.getParent() != null;
}

Try / catch

try {
    client.writeFile(store, path, blob);
} catch (BeaconClientException e) {
    if (e.getMessage().contains("is not absolute")) {
        client.writeFile(store, remoteRoot.resolve(path).normalize(), blob);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling the fs write endpoint with msg.getPath() relative (e.g. 'out.bin'), usually from code that built the path from a working directory assumption or a truncated config value.

Common situations: Uploading files with user-supplied relative names; reusing read-side paths that happened to be relative; templated scripts where the base directory variable was empty, leaving 'sub/file' instead of '/base/sub/file'.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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