github/copilot-sdk · error · IllegalArgumentException
TcpConnectionToken cannot be used with UseStdio = true
Error message
TcpConnectionToken cannot be used with UseStdio = true
What it means
A TCP connection token implies connecting over TCP, while UseStdio = true implies launching and talking to the CLI over stdio. The two transports are mutually exclusive, so the constructor rejects the combination with IllegalArgumentException.
Solutions
- Remove the tcpConnectionToken if you intend stdio transport (setUseStdio(true))
- Set UseStdio = false if you intend TCP transport and keep the token
- Split into two options objects, one per transport mode
Example fix
// before options.setUseStdio(true); options.setTcpConnectionToken(token); // after options.setUseStdio(false); // TCP mode options.setTcpConnectionToken(token);
Defensive patterns
Strategy: validation
Validate before calling
if (options.getTcpConnectionToken() != null && options.isUseStdio()) throw new IllegalStateException("tcpConnectionToken and UseStdio are mutually exclusive"); Try / catch
try { new CopilotClient(options); } catch (IllegalArgumentException e) { if (e.getMessage().contains("cannot be used with UseStdio")) { options.setTcpConnectionToken(null); } else throw e; } Prevention
- Decide the transport (stdio vs tcp) once in a single options factory
- Never set the token unconditionally in shared builders
When it happens
Trigger: new CopilotClient(...) with options where both setTcpConnectionToken(nonEmpty) and setUseStdio(true) are set.
Common situations: Copy-pasted options from a TCP-mode example onto a stdio-mode app; a shared options builder that always sets the token; enabling stdio debugging while keeping an old TCP token.
Related errors
- TcpConnectionToken must be a non-empty string
- CliUrl is mutually exclusive with CliPath
- GitHubToken and UseLoggedInUser cannot be used with CliUrl…
- CopilotClient was created with Mode = EMPTY but neither…
- Invalid value ' '. Expected 'inprocess', 'stdio', or unset.
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/99800ff183589295.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/CopilotClient.java:197
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())
|| (this.options.getCliUrl() != null && !this.options.getCliUrl().isEmpty());
if (!hasPersistence) {
throw new IllegalArgumentException(View on GitHub (pinned to cd8cf15dc3)