github/copilot-sdk · error · IllegalArgumentException

CopilotClient was created with Mode = EMPTY but neither…

Error message

CopilotClient was created with Mode = EMPTY but neither CopilotHome nor CliUrl was set. Empty mode requires an explicit per-session persistence location.

What it means

CopilotClientMode.EMPTY gives the client no default persistence location, so it requires an explicit per-session persistence location: either CopilotHome (a directory) or CliUrl (an external server that manages its own home). If neither is set, the constructor throws IllegalArgumentException rather than silently picking a shared location that could corrupt session state.

Solutions

  1. Set a unique copilotHome directory for the session
  2. Or set cliUrl to point at an external server managing persistence
  3. Or use a different CopilotClientMode if per-session isolation is not needed

Example fix

// before
options.setMode(CopilotClientMode.EMPTY);
// after
options.setMode(CopilotClientMode.EMPTY);
options.setCopilotHome("/tmp/copilot-session-" + sessionId);
Defensive patterns

Strategy: validation

Validate before calling

if (mode == CopilotClientMode.EMPTY && isBlank(home) && isBlank(cliUrl)) throw new IllegalArgumentException("EMPTY mode needs copilotHome or cliUrl");

Try / catch

try { new CopilotClient(options); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Mode = EMPTY")) { options.setCopilotHome(...); } else throw e; }

Prevention

When it happens

Trigger: new CopilotClient(...) with options.setMode(CopilotClientMode.EMPTY) and both getCopilotHome() null/empty and getCliUrl() null/empty.

Common situations: Switching a client to EMPTY mode for isolation but forgetting to set a per-session CopilotHome; building options dynamically where both fields stayed null.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/70b9e6c24a6f9566. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/CopilotClient.java:215

                throw new IllegalArgumentException("TcpConnectionToken cannot be used with UseStdio = true");
            }
        }

        // Compute effective connection token: use provided, or auto-generate for
        // SDK-spawned TCP mode, or null for stdio/external server
        boolean sdkSpawnsCli = !this.options.isUseStdio()
                && (this.options.getCliUrl() == null || this.options.getCliUrl().isEmpty());
        this.effectiveConnectionToken = this.options.getTcpConnectionToken() != null
                ? this.options.getTcpConnectionToken()
                : (sdkSpawnsCli ? java.util.UUID.randomUUID().toString() : null);

        // Empty mode: validate at construction time that the app supplied a
        // per-session persistence location.
        if (this.options.getMode() == CopilotClientMode.EMPTY) {
            boolean hasPersistence = (this.options.getCopilotHome() != null && !this.options.getCopilotHome().isEmpty())
                    || (this.options.getCliUrl() != null && !this.options.getCliUrl().isEmpty());
            if (!hasPersistence) {
                throw new IllegalArgumentException(
                        "CopilotClient was created with Mode = EMPTY but neither CopilotHome nor CliUrl was set. "
                                + "Empty mode requires an explicit per-session persistence location.");
            }
        }

        // Parse CliUrl if provided
        if (this.options.getCliUrl() != null && !this.options.getCliUrl().isEmpty()) {
            URI uri = CliServerManager.parseCliUrl(this.options.getCliUrl());
            String host = uri.getHost();
            this.optionsHost = host != null && host.startsWith("[") && host.endsWith("]")
                    ? host.substring(1, host.length() - 1)
                    : host;
            this.optionsPort = uri.getPort();
        } else {
            this.optionsHost = null;
            this.optionsPort = null;
        }

View on GitHub (pinned to cd8cf15dc3)