xpipe-io/xpipe · error · BeaconClientException
Connection " + DataStorage.get().getStorePath(e).toString()
Error message
Connection " + DataStorage.get().getStorePath(e).toString() + " is not a shell connection
What it means
After a unique connection is resolved, the exchange checks that its DataStore implements ShellStore. Non-shell connections cannot be opened in an external terminal as a shell, so the handler throws with the full store path for clarity.
Source
Thrown at app/src/main/java/io/xpipe/app/beacon/api/TerminalExternalLaunchExchange.java:44
return "/terminal/externalLaunch";
}
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException, BeaconServerException {
var found = DataStorageQuery.queryUserInput(msg.getConnection());
if (found.isEmpty()) {
throw new BeaconClientException("No connection found for input " + msg.getConnection());
}
if (found.size() > 1) {
throw new BeaconClientException("Multiple stores found: "
+ found.stream().map(DataStoreEntry::getName).toList());
}
var e = found.getFirst();
var isShell = e.getStore() instanceof ShellStore;
if (!isShell) {
throw new BeaconClientException(
"Connection " + DataStorage.get().getStorePath(e).toString() + " is not a shell connection");
}
if (!checkPermission()) {
return Response.builder().command(List.of()).build();
}
var r = TerminalLauncherManager.externalExchange(e.ref(), msg.getArguments());
return Response.builder().command(r).build();
}
@Override
public boolean requiresEnabledApi() {
return false;
}
@Override
public Object getSynchronizationObject() {View on GitHub (pinned to d85ca821ba)
Solutions
- Target the shell sub-connection of the store (e.g. the SSH child) rather than the parent
- Check e.getStore() instanceof ShellStore before launching
- Use the shell/start API for shell session management instead of external launch
- Create a shell-capable connection for the host you need
Example fix
// before
client.terminalLaunch("my-database"); // not a shell
// after
if (entry.getStore() instanceof ShellStore) {
client.terminalLaunch(entry.getUuid());
} else {
client.terminalLaunch("my-database/ssh"); // shell child
} Defensive patterns
Strategy: type-guard
Validate before calling
DataStoreEntry e = found.getFirst();
if (!(e.getStore() instanceof ShellStore)) throw new IllegalArgumentException("not a shell: " + e.getName()); Type guard
static boolean isShell(DataStoreEntry e) {
return e.getStore() instanceof ShellStore;
} Try / catch
try {
client.terminalLaunch(input);
} catch (BeaconClientException ex) {
if (ex.getMessage().contains("is not a shell connection")) {
// target a shell sub-connection instead
} else throw ex;
} Prevention
- Check instanceof ShellStore before terminal launch
- Target shell sub-connections of composite stores
- Filter search results to shell stores
When it happens
Trigger: Calling terminal/external launch with a connection whose store is not a ShellStore — e.g. a script, vault, data-store (database), or custom store entry.
Common situations: Scripts pick the first search result without checking its type; user passes a database or script connection where a shell was expected; a connection that previously hosted a shell sub-connection was targeted directly instead of its shell child.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Not a shell connection
- No connection found for input " + msg.getConnection()
- Multiple stores found: " + storeNames
- Unable to parse store data into valid store
- Category with id " + msg.getCategory() + " does not exist
AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06).
Data as JSON: /api/errors/609a6dabe16ec3ca.
Report an issue: GitHub.