xpipe-io/xpipe · error · BeaconClientException

Connection is not a shell connection

Error message

Connection ${path} is not a shell connection

What it means

McpToolHandler.getShellStoreRef resolves a connection ref and then asserts the underlying store is an instance of ShellStore. When the resolved connection is a different store kind (e.g. a database, HTTP, or script store), it throws this BeaconClientException naming the store path.

Solutions

  1. Pass the name of an actual shell connection (SSH, local shell, serial, etc.)
  2. Inspect the connection's type in the XPipe UI; create an SSH/local shell connection if needed
  3. If the target is a database, use the database-specific MCP tool instead of the shell one
  4. Catch BeaconClientException and report that the chosen connection type is unsupported for shell operations

Example fix

// before
req.getShellStoreRef("prod-postgres", false) // database store
// after
req.getShellStoreRef("prod-postgres-host", false) // SSH shell connection to the host
Defensive patterns

Strategy: type-guard

Validate before calling

// check the connection type before the shell tool call
const conn = await getConnection(name);
if (conn.storeType !== 'shell') {
  throw new Error(`connection '${name}' is a ${conn.storeType} store; a shell connection is required`);
}

Type guard

function isShellConnection(conn) { return conn != null && typeof conn.storeType === 'string' && conn.storeType.toLowerCase().includes('shell'); }

Try / catch

try { return shellTool.call({name}); } catch (BeaconClientException e) { if (e.message.includes('is not a shell connection')) { /* switch to the matching tool for that store kind */ } throw e; }

Prevention

When it happens

Trigger: Calling an MCP shell tool (shell command execution, file read/list) and passing a connection name whose DataStore is not a ShellStore — e.g. a database connection, an API/http connection, or a custom store.

Common situations: Selecting a database or Kubernetes connection where a shell connection was expected; confusing a Proxmox/hypervisor container entry with its SSH connection; reusing a name from a different tool context.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at app/src/main/java/io/xpipe/app/beacon/mcp/McpToolHandler.java:158

            if (found.size() > 1) {
                throw new BeaconClientException("Multiple connections found: "
                        + found.stream()
                                .map(entry ->
                                        DataStorage.get().getStorePath(entry).toString())
                                .toList());
            }

            var e = found.getFirst();
            return e.ref();
        }

        public DataStoreEntryRef<ShellStore> getShellStoreRef(String name, boolean mutation)
                throws BeaconClientException {
            var ref = getDataStoreRef(name);
            var isShell = ref.getStore() instanceof ShellStore;
            if (!isShell) {
                throw new BeaconClientException("Connection "
                        + DataStorage.get().getStorePath(ref.get()).toString() + " is not a shell connection");
            }

            var disableMutation =
                    DataStorage.get().getEffectiveCategoryConfig(ref.get()).getDontAllowScripts();
            if (mutation && disableMutation != null && disableMutation) {
                throw new BeaconClientException("Modifications to connection "
                        + DataStorage.get().getStorePath(ref.get()).toString()
                        + " is disabled by the category setting");
            }

            return ref.asNeeded();
        }
    }
}

View on GitHub (pinned to d85ca821ba)