xpipe-io/xpipe · error · BeaconClientException

File ${path} does not exist

Error message

File ${path} does not exist

What it means

The MCP readFile tool opens a ShellFileSystem on the target shell and checks fs.fileExists(path) before reading; if the file is absent it throws this BeaconClientException including the resolved path (tilde already expanded against the user home). This is a pre-flight existence check, not an I/O failure.

Source

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

                                    JacksonMapper.getDefault().writeValueAsString(object))
                            .build();
                }))
                .build();
    }

    public static McpServerFeatures.SyncToolSpecification readFile() throws IOException {
        var tool = McpSchemaFiles.loadTool("read_file.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)) {
                        throw new BeaconClientException("File " + path + " does not exist");
                    }

                    try (var in = fs.openInput(path)) {
                        var b = in.readAllBytes();
                        var s = new String(b, StandardCharsets.UTF_8);
                        return McpSchema.CallToolResult.builder()
                                .addTextContent(s)
                                .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) -> {

View on GitHub (pinned to d85ca821ba)

Solutions

  1. Verify the file exists via the listFiles tool or an ls call on the same connection before reading
  2. Use an absolute path to remove working-directory ambiguity
  3. Check path casing exactly; Linux shells are case-sensitive
  4. Catch BeaconClientException and fall back to listing the parent directory to find the correct name

Example fix

// before
{"system": "my-ssh", "path": "~/Config/app.conf"} // file absent
// after: confirm with listFiles on the parent directory, then
{"system": "my-ssh", "path": "~/config/app.conf"}
Defensive patterns

Strategy: validation

Validate before calling

// existence check via listFiles before reading
const parent = path.substring(0, path.lastIndexOf('/')) || '/';
const entries = await listFiles(system, parent);
if (!entries.some(e => e.path === path)) {
  throw new Error(`file '${path}' not found on '${system}'`);
}

Try / catch

try { return readFile(system, path); } catch (BeaconClientException e) { if (e.message.includes('does not exist')) { /* list parent directory and retry with corrected path */ } throw e; }

Prevention

When it happens

Trigger: Calling the MCP readFile tool with a 'path' that does not exist on the remote/local shell filesystem: typo, wrong relative base, file deleted, or case-mismatch on case-sensitive filesystems.

Common situations: Assuming the working directory differs from the shell's actual home; case-sensitive Linux paths vs case-insensitive local dev; referencing a file on the wrong connection (file exists on another host).

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/353918aa49f0728d. Report an issue: GitHub.