{"record":{"id":"6c6def31526c79f3","repo":"github/copilot-sdk","slug":"copilotclient-is-in-mode-empty-but-the-session-c","errorCode":null,"errorMessage":"CopilotClient is in Mode = EMPTY but the session config did not specify availableTools. Empty mode requires every session to explicitly opt into the tools it wants — e.g. setAvailableTools(new ToolSet().addBuiltIn(BuiltInTools.ISOLATED)).","messagePattern":"CopilotClient is in Mode = EMPTY but the session config did not specify availableTools\\. Empty mode requires every session to explicitly opt into the tools it wants — e\\.g\\. setAvailableTools\\(new ToolSet\\(\\)\\.addBuiltIn\\(BuiltInTools\\.ISOLATED\\)\\)\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/CopilotClient.java","lineNumber":961,"sourceCode":"            var request = SessionRequestBuilder.buildCreateRequest(config, localSessionId, options.getMode());\n            if (extracted.wireSystemMessage() != config.getSystemMessage()) {\n                request.setSystemMessage(extracted.wireSystemMessage());\n            }\n\n            // Opt this session into GitHub telemetry forwarding when a\n            // connection-level handler is registered (mirrors the runtime's\n            // hand-written capability flag, not part of the codegen'd contract).\n            if (options.getOnGitHubTelemetry() != null) {\n                request.setEnableGitHubTelemetryForwarding(true);\n            }\n\n            // Empty mode: validate availableTools and set toolFilterPrecedence\n            if (options.getMode() == CopilotClientMode.EMPTY) {\n                if (config.getAvailableTools() == null) {\n                    if (registeredIdHolder[0] != null) {\n                        sessions.remove(registeredIdHolder[0]);\n                    }\n                    throw new IllegalArgumentException(\n                            \"CopilotClient is in Mode = EMPTY but the session config did not specify \"\n                                    + \"availableTools. Empty mode requires every session to explicitly opt into \"\n                                    + \"the tools it wants — e.g. setAvailableTools(new ToolSet().addBuiltIn(BuiltInTools.ISOLATED)).\");\n                }\n                request.setToolFilterPrecedence(\"excluded\");\n                if (request.getSkipEmbeddingRetrieval() == null) {\n                    request.setSkipEmbeddingRetrieval(true);\n                }\n                if (request.getEmbeddingCacheStorage() == null) {\n                    request.setEmbeddingCacheStorage(\"in-memory\");\n                }\n                if (request.getEnableOnDemandInstructionDiscovery() == null) {\n                    request.setEnableOnDemandInstructionDiscovery(false);\n                }\n                if (request.getEnableFileHooks() == null) {\n                    request.setEnableFileHooks(false);\n                }\n                if (request.getEnableHostGitOperations() == null) {","sourceCodeStart":943,"sourceCodeEnd":979,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/CopilotClient.java#L943-L979","documentation":"In CopilotClientMode.EMPTY, no default tool set is assumed; every session must explicitly opt into the tools it wants via the session config's availableTools. If a createSession-style call omits availableTools, the constructor throws IllegalArgumentException and removes the partially registered session, leaving no orphan state.","triggerScenarios":"Creating a session on a client in Mode = EMPTY where config.getAvailableTools() == null (setAvailableTools never called on the session config).","commonSituations":"Migrating a client to EMPTY mode for least-privilege tooling but not updating every session creation site; dynamic session configs where the tool set was conditionally skipped.","solutions":["Call setAvailableTools(...) on the session config, e.g. new ToolSet().addBuiltIn(BuiltInTools.ISOLATED)","Or switch the client to a non-EMPTY mode if implicit tool defaults are desired","Audit all session-creation call sites to ensure each passes availableTools"],"exampleFix":"// before\nSessionConfig config = new SessionConfig();\n// after\nSessionConfig config = new SessionConfig();\nconfig.setAvailableTools(new ToolSet().addBuiltIn(BuiltInTools.ISOLATED));","handlingStrategy":"validation","validationCode":"if (client.getOptions().getMode() == CopilotClientMode.EMPTY && sessionConfig.getAvailableTools() == null) throw new IllegalStateException(\"EMPTY mode requires setAvailableTools on every session config\");","typeGuard":null,"tryCatchPattern":"try { client.createSession(config).join(); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"Mode = EMPTY but the session config did not specify\")) { config.setAvailableTools(new ToolSet().addBuiltIn(BuiltInTools.ISOLATED)); } else throw e; }","preventionTips":["Use a session-config factory that always sets availableTools in EMPTY mode","Audit every createSession call site when adopting EMPTY mode","Default to an explicit minimal ToolSet rather than null"],"tags":["java","empty-mode","tools","session"],"backgroundTag":"missing-required-config-field","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}