github/copilot-sdk · error · IllegalArgumentException

TcpConnectionToken must be a non-empty string

Error message

TcpConnectionToken must be a non-empty string

What it means

CopilotClient validates at construction that the tcpConnectionToken option, when provided, is a non-empty string. An empty string is treated as an invalid configuration rather than 'not provided', so the constructor throws IllegalArgumentException immediately. Set the option to null to omit it instead of passing "".

Solutions

  1. Pass null instead of "" when you have no TCP connection token
  2. Supply the actual token generated by the SDK or your TCP server
  3. Trim the config/env value and treat blank as absent before calling setTcpConnectionToken

Example fix

// before
options.setTcpConnectionToken("");
// after
String token = System.getenv("COPILOT_TCP_TOKEN");
if (token != null && !token.isBlank()) options.setTcpConnectionToken(token.trim());
Defensive patterns

Strategy: validation

Validate before calling

if (token != null && token.isEmpty()) throw new IllegalArgumentException("tcpConnectionToken must be empty or absent");

Type guard

boolean isValidTcpToken(String t) { return t == null || !t.isEmpty(); }

Try / catch

try { new CopilotClient(options); } catch (IllegalArgumentException e) { if (e.getMessage().contains("TcpConnectionToken")) { /* fix options */ } else throw e; }

Prevention

When it happens

Trigger: new CopilotClient(...) with CopilotClientOptions where setTcpConnectionToken("") or an options object built from an empty/blank config value or environment variable was used while isUseStdio() handling requires a real token.

Common situations: Reading the token from an env var or properties file that exists but is empty; string interpolation producing ""; default-initializing the option to "" instead of null.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

        }

        // Validate mutually exclusive options: cliUrl and cliPath cannot both be set
        if (this.options.getCliUrl() != null && !this.options.getCliUrl().isEmpty()
                && this.options.getCliPath() != null) {
            throw new IllegalArgumentException("CliUrl is mutually exclusive with CliPath");
        }

        // Validate auth options with external server
        if (this.options.getCliUrl() != null && !this.options.getCliUrl().isEmpty()
                && (this.options.getGitHubToken() != null || this.options.getUseLoggedInUser().isPresent())) {
            throw new IllegalArgumentException(
                    "GitHubToken and UseLoggedInUser cannot be used with CliUrl (external server manages its own auth)");
        }

        // Validate tcpConnectionToken
        if (this.options.getTcpConnectionToken() != null) {
            if (this.options.getTcpConnectionToken().isEmpty()) {
                throw new IllegalArgumentException("TcpConnectionToken must be a non-empty string");
            }
            if (this.options.isUseStdio()) {
                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())

View on GitHub (pinned to cd8cf15dc3)