xpipe-io/xpipe · error · BeaconClientException
Directory ${path} does not exist
Error message
Directory ${path} does not exist What it means
The MCP listFiles tool checks fs.directoryExists(path) on the target shell before enumerating; if the path is not an existing directory it throws this BeaconClientException with the resolved path. This also fires when the path exists but is a regular file, since it must be a directory.
Source
Thrown at app/src/main/java/io/xpipe/app/beacon/mcp/McpTools.java:244
.build();
}
}))
.build();
}
public static McpServerFeatures.SyncToolSpecification listFiles() throws IOException {
var tool = McpSchemaFiles.loadTool("list_files.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 fs = new ShellFileSystem(shellSession.getControl());
var path = req.getFilePath(shellSession.getControl(), "path");
if (!fs.directoryExists(path)) {
throw new BeaconClientException("Directory " + path + " does not exist");
}
try (var stream = fs.listFiles(fs, path)) {
var list = stream.toList();
var builder = McpSchema.CallToolResult.builder();
for (FileEntry e : list) {
builder.addTextContent(e.getPath().toString());
}
return builder.build();
}
}))
.build();
}
public static McpServerFeatures.SyncToolSpecification findFile() throws IOException {
var tool = McpSchemaFiles.loadTool("find_file.json");
return McpServerFeatures.SyncToolSpecification.builder()
.tool(tool)View on GitHub (pinned to d85ca821ba)
Solutions
- Verify the directory exists on that connection (e.g. readFile a known file or run an ls via another tool) before listing
- Use an absolute directory path rather than a relative or '~'-based guess
- If the path is a file, read it with readFile instead of listing it
- Catch BeaconClientException and fall back to listing the parent directory to discover the correct name
Example fix
// before
{"system": "my-ssh", "path": "~/logs"} // directory absent
// after
{"system": "my-ssh", "path": "/var/log"} Defensive patterns
Strategy: validation
Validate before calling
// verify the path is an existing directory before listing
const parent = path.substring(0, path.lastIndexOf('/')) || '/';
const entries = await listFiles(system, parent); // throws if parent missing
const target = entries.find(e => e.path === path);
if (!target || !target.isDirectory) {
throw new Error(`'${path}' is not a directory on '${system}'`);
} Type guard
function isDirectoryEntry(e) { return e != null && e.isDirectory === true; } Try / catch
try { return listFiles(system, path); } catch (BeaconClientException e) { if (e.message.includes('does not exist')) { /* fall back to listing the parent or reading as a file */ } throw e; } Prevention
- Distinguish files from directories before choosing readFile vs listFiles
- Use absolute directory paths; verify '~' resolves to the expected home
- Confirm the directory still exists on the remote before scripted listing
When it happens
Trigger: Calling the MCP listFiles tool with a 'path' that is missing on the shell, or that points to a regular file instead of a directory; tilde-expanded path resolved against the connection user's home.
Common situations: Listing '~' paths whose home differs from expectation; pointing at a file (e.g. /etc/hosts) rather than a directory; directory removed or renamed on the remote; wrong connection selected.
Related errors
- File ${path} does not exist
- Directory " + msg.getPath().getParent() + " does not exist
- Missing argument for key " + key
- Invalid argument for key " + key
- No connection found for input " + name
AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06).
Data as JSON: /api/errors/dbcc21fff8fbf364.
Report an issue: GitHub.