{"record":{"id":"538316626e8b8d26","repo":"github/copilot-sdk","slug":"copilotclient-is-in-mode-empty-but-the-resume-se","errorCode":null,"errorMessage":"CopilotClient is in Mode = EMPTY but the resume 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 resume 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":1150,"sourceCode":"                session.registerTransformCallbacks(extracted.transformCallbacks());\n            }\n            var request = SessionRequestBuilder.buildResumeRequest(sessionId, config, 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 for resume\n            // path\n            if (options.getMode() == CopilotClientMode.EMPTY) {\n                if (config.getAvailableTools() == null) {\n                    throw new IllegalArgumentException(\n                            \"CopilotClient is in Mode = EMPTY but the resume 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":1132,"sourceCodeEnd":1168,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/CopilotClient.java#L1132-L1168","documentation":"In CopilotClientMode.EMPTY the client never exposes tools implicitly: every session must explicitly declare its availableTools. When resuming a session in EMPTY mode whose config has availableTools == null, the client throws IllegalArgumentException because no tool filter could be derived.","triggerScenarios":"Calling resumeSession (or creating a resume request) on a client constructed with mode = EMPTY while the resume config's getAvailableTools() returns null.","commonSituations":"Code that worked in default mode reused for an EMPTY-mode client; config objects deserialized from JSON missing the availableTools field; migrating sessions to EMPTY mode without updating resume paths.","solutions":["Set availableTools on the resume config, e.g. new ToolSet().addBuiltIn(BuiltInTools.ISOLATED)","Change the client mode away from EMPTY if implicit tools are desired","Add a config-validation step before resume that rejects null availableTools in EMPTY mode"],"exampleFix":"// before\nclient.resumeSession(config); // config.availableTools == null, mode == EMPTY\n// after\nconfig.setAvailableTools(new ToolSet().addBuiltIn(BuiltInTools.ISOLATED));\nclient.resumeSession(config);","handlingStrategy":"validation","validationCode":"if (clientOptions.getMode() == CopilotClientMode.EMPTY && resumeConfig.getAvailableTools() == null) {\n    throw new IllegalArgumentException(\"EMPTY mode requires availableTools on resume config\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    client.resumeSession(config);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"did not specify availableTools\")) {\n        config.setAvailableTools(new ToolSet().addBuiltIn(BuiltInTools.ISOLATED));\n        client.resumeSession(config);\n    }\n}","preventionTips":["Centralize resume-config construction so availableTools is always set in EMPTY mode","Validate configs at load time (fail fast on missing availableTools when mode==EMPTY)","Document EMPTY-mode requirements in your config schema"],"tags":["config","tools","empty-mode"],"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"}