xpipe-io/xpipe · error · BeaconClientException
File path " + msg.getPath() + " is not absolute
Error message
File path " + msg.getPath() + " is not absolute
What it means
FsReadExchange requires an absolute file path on the target filesystem. The client sent a relative path, and the shell-based filesystem cannot resolve it unambiguously (the working directory of the remote shell is not part of the API contract). The daemon fails fast before touching the filesystem.
Source
Thrown at app/src/main/java/io/xpipe/app/beacon/api/FsReadExchange.java:37
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.UUID;
public class FsReadExchange extends BeaconInterface<FsReadExchange.Request> {
@Override
public String getPath() {
return "/fs/read";
}
@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.fileExists(msg.getPath())) {
throw new BeaconClientException("File " + msg.getPath() + " does not exist");
}
var size = fs.getFileSize(msg.getPath());
if (size > 100_000_000) {
var file = BlobManager.get().newBlobFile();
try (var in = fs.openInput(msg.getPath())) {
var fixedIn = new FixedSizeInputStream(new BufferedInputStream(in), size);
try (var fileOut = Files.newOutputStream(file)) {
fixedIn.transferTo(fileOut);
}
in.transferTo(OutputStream.nullOutputStream());
}
exchange.sendResponseHeaders(200, size);View on GitHub (pinned to d85ca821ba)
Solutions
- Normalize the path to absolute before calling: prefix with the known base directory
- Use Path.toAbsolutePath() (or equivalent) on the client side against the intended base dir
- For remote systems, anchor to a known root such as '/' or the user's home obtained from the shell
- Validate with path.isAbsolute() and reject or resolve before sending
Example fix
// before
client.readFile(store, Path.of("logs/app.log"));
// after
Path p = Path.of("logs/app.log");
if (!p.isAbsolute()) {
p = homeDir.resolve(p).normalize();
}
client.readFile(store, p); Defensive patterns
Strategy: validation
Validate before calling
if (path == null || !path.isAbsolute()) {
throw new IllegalArgumentException("Path must be absolute: " + path);
} Type guard
boolean isUsableRemotePath(Path p) {
return p != null && p.isAbsolute() && !p.normalize().toString().contains("..");
} Try / catch
try {
client.readFile(store, path);
} catch (BeaconClientException e) {
if (e.getMessage().contains("is not absolute")) {
path = baseDir.resolve(path).normalize();
client.readFile(store, path);
} else throw e;
} Prevention
- Always resolve user-supplied paths against an explicit base directory
- Remember remote resolution depends on the target OS (drive letters on Windows)
- Reject relative paths at your API boundary
When it happens
Trigger: Calling the fs read beacon endpoint with msg.getPath() set to a relative path like 'file.txt' or './sub/file.txt' instead of an absolute path such as '/etc/file.txt' or 'C:\\file.txt'.
Common situations: User-supplied paths passed straight through to the API; composing paths from a config value missing its leading separator; paths constructed on Windows-style vs POSIX-style systems and then used remotely; scripts running from a working directory and assuming relative resolution.
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
- File path " + msg.getPath() + " is not absolute
- File " + msg.getPath() + " does not exist
- Directory " + msg.getPath().getParent() + " does not exist
- Cannot delete category: " + cat.getName()
- Unsupported mode: " + msg.getMode().getDisplayName() + ". Su
AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06).
Data as JSON: /api/errors/c072b9df166b496f.
Report an issue: GitHub.