xpipe-io/xpipe · error · BeaconClientException
Not a shell connection
Error message
Not a shell connection
What it means
XPipe's beacon HTTP API throws this when a client requests a shell action (shell/start) against a store entry whose underlying DataStore is not a ShellStore. Only connections that actually provide a shell (SSH, local shell, etc.) can start shell sessions, so the handler rejects non-shell stores early with a typed BeaconClientException.
Source
Thrown at app/src/main/java/io/xpipe/app/beacon/api/ShellStartExchange.java:36
import lombok.extern.jackson.Jacksonized;
import java.util.UUID;
public class ShellStartExchange extends BeaconInterface<ShellStartExchange.Request> {
@Override
public String getPath() {
return "/shell/start";
}
@Override
@SneakyThrows
public Object handle(HttpExchange exchange, Request msg) {
var e = DataStorage.get()
.getStoreEntryIfPresent(msg.getStore())
.orElseThrow(() -> new BeaconClientException("Unknown connection"));
if (!(e.getStore() instanceof ShellStore s)) {
throw new BeaconClientException("Not a shell connection");
}
var existing = AppBeaconServer.get().getCache().getShellSessions().stream()
.filter(beaconShellSession -> beaconShellSession.getEntry().equals(e))
.findFirst();
var control = (existing.isPresent()
? existing.get().getControl()
: s.standaloneControl().start());
control.setNonInteractive();
control.start();
var d = control.getShellDialect().getDumbMode();
if (!d.supportsAnyPossibleInteraction()) {
control.close();
d.throwIfUnsupported();
}
if (existing.isEmpty()) {View on GitHub (pinned to d85ca821ba)
Solutions
- Verify the connection is a shell-type connection (SSH, local, WSL, docker, etc.) in the XPipe UI before targeting it
- Check the store type client-side before calling: e instanceof ShellStore or inspect the store's type in the listing response
- Use the correct beacon endpoint for the store kind you actually have
- If you need a shell on a non-shell store, add a shell-capable sub-connection to it and target that instead
Example fix
// before
client.shellStart(storeUuid); // store may not be a shell
// after
DataStoreEntry e = DataStorage.get().getStoreEntry(storeUuid);
if (e.getStore() instanceof ShellStore) {
client.shellStart(storeUuid);
} else {
throw new IllegalArgumentException(storeUuid + " is not a shell connection");
} Defensive patterns
Strategy: type-guard
Validate before calling
DataStoreEntry e = DataStorage.get().getStoreEntryIfPresent(uuid).orElse(null); boolean ok = e != null && e.getStore() instanceof ShellStore;
Type guard
static boolean isShellConnection(DataStoreEntry e) {
return e != null && e.getStore() instanceof ShellStore;
} Try / catch
try {
client.shellStart(req);
} catch (BeaconClientException ex) {
if (ex.getMessage().contains("Not a shell connection")) {
// fall back to a different connection or skip
} else throw ex;
} Prevention
- Check store type before shell operations
- Only iterate shell-type connections in automation
- Use the store listing API to filter by type
When it happens
Trigger: Calling the POST /shell/start beacon endpoint (ShellStartExchange.handle) with a store UUID whose DataStore does not implement ShellStore, e.g. a script group, custom store, or category-like entry.
Common situations: Automation scripts iterate over all connections and blindly call shell start on every store; users pass the UUID of a non-shell connection; a store type changed after an update so a previously shell-capable store no longer is.
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
- Connection " + DataStorage.get().getStorePath(e).toString()
- No active shell session known for id " + uuid
- Couldn't send request
- Couldn't parse response
- Couldn't parse client error message
AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06).
Data as JSON: /api/errors/a22d20384c929fec.
Report an issue: GitHub.