{"record":{"id":"7ba7fdad278d869b","repo":"github/copilot-sdk","slug":"githubtoken-and-useloggedinuser-cannot-be-used-wit-7ba7fd","errorCode":null,"errorMessage":"GitHubToken and UseLoggedInUser cannot be used with CliUrl (external server manages its own auth)","messagePattern":"GitHubToken and UseLoggedInUser cannot be used with CliUrl \\(external server manages its own auth\\)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/CopilotClient.java","lineNumber":187,"sourceCode":"            }\n        }\n        this.runtimeConnection = requestedConnection;\n\n        // When cliUrl is set, auto-correct useStdio since we're connecting via TCP\n        if (this.options.getCliUrl() != null && !this.options.getCliUrl().isEmpty()) {\n            this.options.setUseStdio(false);\n        }\n\n        // Validate mutually exclusive options: cliUrl and cliPath cannot both be set\n        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","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/CopilotClient.java#L169-L205","documentation":"When CopilotClient connects to an external server via CliUrl, that server manages its own authentication, so supplying GitHubToken or UseLoggedInUser is contradictory. The constructor throws IllegalArgumentException to prevent conflicting auth configuration. Auth options are only meaningful when the client drives a local CLI.","triggerScenarios":"Constructing CopilotClient with a non-empty cliUrl plus either a non-null githubToken or a present useLoggedInUser option.","commonSituations":"Reusing a shared options builder that always sets GitHubToken; switching from local CLI to external-server mode without removing auth fields; environment-injected tokens (e.g. GITHUB_TOKEN) wired into options unconditionally.","solutions":["Omit githubToken and useLoggedInUser when cliUrl is set — the external server authenticates itself.","Conditionally set auth options only when cliPath/local-CLI mode is used.","Move auth configuration to the external server instead of the client options."],"exampleFix":"// before\noptions.setCliUrl(\"http://localhost:8080\");\noptions.setGitHubToken(token); // not allowed with CliUrl\n// after\noptions.setCliUrl(\"http://localhost:8080\");\n// no auth options — external server manages auth","handlingStrategy":"validation","validationCode":"boolean external = options.getCliUrl() != null && !options.getCliUrl().isEmpty();\nif (external && (options.getGitHubToken() != null || options.getUseLoggedInUser().isPresent())) {\n    options.setGitHubToken(null);\n}","typeGuard":null,"tryCatchPattern":"try {\n  client = new CopilotClient(options);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"cannot be used with CliUrl\")) {\n    options.setGitHubToken(null);\n    client = new CopilotClient(options);\n  } else throw e;\n}","preventionTips":["Only set auth options in local-CLI mode; the external server owns its auth.","Don't wire environment tokens (e.g. GITHUB_TOKEN) into options unconditionally.","Use separate option builders for external-server and local-CLI modes."],"tags":["java","configuration","authentication","client-construction"],"backgroundTag":"conflicting-config-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"}