{"record":{"id":"c072b9df166b496f","repo":"xpipe-io/xpipe","slug":"file-path-msg-getpath-is-not-absolute","errorCode":null,"errorMessage":"File path \" + msg.getPath() + \" is not absolute","messagePattern":"File path \" \\+ msg\\.getPath\\(\\) \\+ \" is not absolute","errorType":"exception","errorClass":"BeaconClientException","httpStatus":400,"severity":"error","filePath":"app/src/main/java/io/xpipe/app/beacon/api/FsReadExchange.java","lineNumber":37,"sourceCode":"import java.io.OutputStream;\nimport java.nio.file.Files;\nimport java.util.UUID;\n\npublic class FsReadExchange extends BeaconInterface<FsReadExchange.Request> {\n\n    @Override\n    public String getPath() {\n        return \"/fs/read\";\n    }\n\n    @Override\n    @SneakyThrows\n    public Object handle(HttpExchange exchange, Request msg) {\n        var shell = AppBeaconServer.get().getCache().getShellSession(msg.getStore());\n        var fs = new ShellFileSystem(shell.getControl());\n\n        if (!msg.getPath().isAbsolute()) {\n            throw new BeaconClientException(\"File path \" + msg.getPath() + \" is not absolute\");\n        }\n\n        if (!fs.fileExists(msg.getPath())) {\n            throw new BeaconClientException(\"File \" + msg.getPath() + \" does not exist\");\n        }\n\n        var size = fs.getFileSize(msg.getPath());\n        if (size > 100_000_000) {\n            var file = BlobManager.get().newBlobFile();\n            try (var in = fs.openInput(msg.getPath())) {\n                var fixedIn = new FixedSizeInputStream(new BufferedInputStream(in), size);\n                try (var fileOut = Files.newOutputStream(file)) {\n                    fixedIn.transferTo(fileOut);\n                }\n                in.transferTo(OutputStream.nullOutputStream());\n            }\n\n            exchange.sendResponseHeaders(200, size);","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/xpipe-io/xpipe/blob/d85ca821baa46092a320ebb13546d7240adb74f8/app/src/main/java/io/xpipe/app/beacon/api/FsReadExchange.java#L19-L55","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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"],"exampleFix":"// before\nclient.readFile(store, Path.of(\"logs/app.log\"));\n// after\nPath p = Path.of(\"logs/app.log\");\nif (!p.isAbsolute()) {\n    p = homeDir.resolve(p).normalize();\n}\nclient.readFile(store, p);","handlingStrategy":"validation","validationCode":"if (path == null || !path.isAbsolute()) {\n    throw new IllegalArgumentException(\"Path must be absolute: \" + path);\n}","typeGuard":"boolean isUsableRemotePath(Path p) {\n    return p != null && p.isAbsolute() && !p.normalize().toString().contains(\"..\");\n}","tryCatchPattern":"try {\n    client.readFile(store, path);\n} catch (BeaconClientException e) {\n    if (e.getMessage().contains(\"is not absolute\")) {\n        path = baseDir.resolve(path).normalize();\n        client.readFile(store, path);\n    } else throw e;\n}","preventionTips":["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"],"tags":["beacon-api","filesystem","path-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"d85ca821baa46092a320ebb13546d7240adb74f8","analyzedAt":"2026-09-06T14:30:08.251Z","contentChangedAt":"2026-09-06T14:30:08.251Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}