{"record":{"id":"99800ff183589295","repo":"github/copilot-sdk","slug":"tcpconnectiontoken-cannot-be-used-with-usestdio","errorCode":null,"errorMessage":"TcpConnectionToken cannot be used with UseStdio = true","messagePattern":"TcpConnectionToken cannot be used with UseStdio = true","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/CopilotClient.java","lineNumber":197,"sourceCode":"        if (this.options.getCliUrl() != null && !this.options.getCliUrl().isEmpty()\n                && this.options.getCliPath() != null) {\n            throw new IllegalArgumentException(\"CliUrl is mutually exclusive with CliPath\");\n        }\n\n        // Validate auth options with external server\n        if (this.options.getCliUrl() != null && !this.options.getCliUrl().isEmpty()\n                && (this.options.getGitHubToken() != null || this.options.getUseLoggedInUser().isPresent())) {\n            throw new IllegalArgumentException(\n                    \"GitHubToken and UseLoggedInUser cannot be used with CliUrl (external server manages its own auth)\");\n        }\n\n        // Validate tcpConnectionToken\n        if (this.options.getTcpConnectionToken() != null) {\n            if (this.options.getTcpConnectionToken().isEmpty()) {\n                throw new IllegalArgumentException(\"TcpConnectionToken must be a non-empty string\");\n            }\n            if (this.options.isUseStdio()) {\n                throw new IllegalArgumentException(\"TcpConnectionToken cannot be used with UseStdio = true\");\n            }\n        }\n\n        // Compute effective connection token: use provided, or auto-generate for\n        // SDK-spawned TCP mode, or null for stdio/external server\n        boolean sdkSpawnsCli = !this.options.isUseStdio()\n                && (this.options.getCliUrl() == null || this.options.getCliUrl().isEmpty());\n        this.effectiveConnectionToken = this.options.getTcpConnectionToken() != null\n                ? this.options.getTcpConnectionToken()\n                : (sdkSpawnsCli ? java.util.UUID.randomUUID().toString() : null);\n\n        // Empty mode: validate at construction time that the app supplied a\n        // per-session persistence location.\n        if (this.options.getMode() == CopilotClientMode.EMPTY) {\n            boolean hasPersistence = (this.options.getCopilotHome() != null && !this.options.getCopilotHome().isEmpty())\n                    || (this.options.getCliUrl() != null && !this.options.getCliUrl().isEmpty());\n            if (!hasPersistence) {\n                throw new IllegalArgumentException(","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/CopilotClient.java#L179-L215","documentation":"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.","triggerScenarios":"new CopilotClient(...) with options where both setTcpConnectionToken(nonEmpty) and setUseStdio(true) are set.","commonSituations":"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.","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"],"exampleFix":"// before\noptions.setUseStdio(true);\noptions.setTcpConnectionToken(token);\n// after\noptions.setUseStdio(false); // TCP mode\noptions.setTcpConnectionToken(token);","handlingStrategy":"validation","validationCode":"if (options.getTcpConnectionToken() != null && options.isUseStdio()) throw new IllegalStateException(\"tcpConnectionToken and UseStdio are mutually exclusive\");","typeGuard":null,"tryCatchPattern":"try { new CopilotClient(options); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"cannot be used with UseStdio\")) { options.setTcpConnectionToken(null); } else throw e; }","preventionTips":["Decide the transport (stdio vs tcp) once in a single options factory","Never set the token unconditionally in shared builders"],"tags":["java","configuration","stdio","tcp"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}