xpipe-io/xpipe · error · IllegalStateException

Local shell not initialized yet

Error message

Local shell not initialized yet

What it means

LocalShell.getShell() returns the cached, lazily-initialized local shell connection. If LocalShell.init() has not yet run (static field local == null), there is no shell to hand out and an IllegalStateException is thrown. This is an initialization-order guard, not a shell failure.

Source

Thrown at app/src/main/java/io/xpipe/app/process/LocalShell.java:122

            localPowershell = ProcModuleProvider.get()
                    .createLocalProcessControl(false)
                    .subShell(ShellDialects.POWERSHELL)
                    .start();
            localPowershell.getShellDialect().getDumbMode().throwIfUnsupported();
        } catch (Exception ex) {
            localPowershell = null;
            ErrorEventFactory.fromThrowable(ex)
                    .description("Failed to start local powershell process")
                    .handle();
        }

        return Optional.ofNullable(localPowershell);
    }

    @SneakyThrows
    public static ShellControl getShell() {
        if (local == null) {
            throw new IllegalStateException("Local shell not initialized yet");
        }

        return local.start();
    }

    public static ShellDialect getDialect() {
        return ProcModuleProvider.get().getEffectiveLocalDialect();
    }
}

View on GitHub (pinned to d85ca821ba)

Solutions

  1. Ensure LocalShell.init() runs before any code that resolves local-machine stores
  2. In tests, call the init/test hook to bootstrap a local shell in setup
  3. Check startup logs for an earlier exception that prevented shell initialization

Example fix

// before
var shell = LocalShell.getShell();
// after
LocalShell.init(); // in setup/bootstrap, before first use
var shell = LocalShell.getShell();
Defensive patterns

Strategy: try-catch

Type guard

boolean localShellReady() { try { var f = LocalShell.class.getDeclaredField("local"); f.setAccessible(true); return f.get(null) != null; } catch (Exception e) { return false; } }

Try / catch

try { var shell = LocalShell.getShell(); ... } catch (IllegalStateException e) { if (e.getMessage().equals("Local shell not initialized yet")) { LocalShell.init(); shell = LocalShell.getShell(); } else throw e; }

Prevention

When it happens

Trigger: Any code path calling LocalShell.getShell() before LocalShell.init() completed, or after initialization failed silently leaving local null.

Common situations: Calling store/query APIs very early during app startup before the local shell bootstrap; unit tests instantiating classes that depend on LocalShell without initializing it; initialization failure swallowed earlier in startup.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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