xpipe-io/xpipe · error · BeaconClientException

Path ${path} does not exist

Error message

Path ${path} does not exist

What it means

Thrown by the getFileInfo MCP tool when the requested path matches neither an existing file nor a directory on the target shell. The first check tests both fileExists() and directoryExists() before attempting to read metadata. A second identical throw happens if the metadata lookup itself returns empty.

Source

Thrown at app/src/main/java/io/xpipe/app/beacon/mcp/McpTools.java:305

                        return builder.build();
                    }
                }))
                .build();
    }

    public static McpServerFeatures.SyncToolSpecification getFileInfo() throws IOException {
        var tool = McpSchemaFiles.loadTool("get_file_info.json");
        return McpServerFeatures.SyncToolSpecification.builder()
                .tool(tool)
                .callHandler(McpToolHandler.of((req) -> {
                    var system = req.getStringArgument("system");
                    var shellStore = req.getShellStoreRef(system, false);
                    var shellSession = AppBeaconServer.get().getCache().getOrStart(shellStore);
                    var path = req.getFilePath(shellSession.getControl(), "path");
                    var fs = new ShellFileSystem(shellSession.getControl());

                    if (!fs.fileExists(path) && !fs.directoryExists(path)) {
                        throw new BeaconClientException("Path " + path + " does not exist");
                    }

                    var entry = fs.getFileInfo(path);
                    if (entry.isEmpty()) {
                        throw new BeaconClientException("Path " + path + " does not exist");
                    }

                    var e = entry.get();
                    var map = new LinkedHashMap<String, Object>();
                    map.put("path", e.getPath().toString());
                    map.put("size", e.getSize());
                    if (e.getInfo() instanceof FileInfo.Unix u) {
                        map.put("permissions", u.getPermissions());
                        map.put("user", u.getUser());
                        map.put("group", u.getGroup());
                    } else if (e.getInfo() instanceof FileInfo.Windows w) {
                        map.put("attributes", w.getAttributes());
                    }

View on GitHub (pinned to d85ca821ba)

Solutions

  1. Check the path exists via a shell listing before calling getFileInfo
  2. Use an absolute path and match case exactly on Unix-like systems
  3. Confirm the 'system' argument refers to the correct connection
  4. Re-run the call if a concurrent process may have briefly removed the path

Example fix

// before
getFileInfo(system: "host", path: "/etc/hosts.bak") // non-existent
// after
getFileInfo(system: "host", path: "/etc/hosts")
Defensive patterns

Strategy: validation

Validate before calling

function assertPathExists(fs, path) {
  if (!fs.fileExists(path) && !fs.directoryExists(path)) throw new Error(`Path ${path} does not exist`);
}

Try / catch

try {
  return await mcp.call('getFileInfo', {system, path});
} catch (e) {
  if (String(e.message).includes('does not exist')) return null; // treat as missing
  throw e;
}

Prevention

When it happens

Trigger: Calling getFileInfo with a 'path' argument that does not exist on the target system, or one that disappears between the exists-check and getFileInfo().

Common situations: Race where the file was removed by another process, symlink pointing to a missing target, wrong system selected, or case-sensitivity mismatches on Linux paths.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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