github/copilot-sdk · error · IllegalArgumentException

CopilotClient is in Mode = EMPTY but the resume session…

Error message

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)).

What it means

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.

Solutions

  1. Set availableTools on the resume config, e.g. new ToolSet().addBuiltIn(BuiltInTools.ISOLATED)
  2. Change the client mode away from EMPTY if implicit tools are desired
  3. Add a config-validation step before resume that rejects null availableTools in EMPTY mode

Example fix

// before
client.resumeSession(config); // config.availableTools == null, mode == EMPTY
// after
config.setAvailableTools(new ToolSet().addBuiltIn(BuiltInTools.ISOLATED));
client.resumeSession(config);
Defensive patterns

Strategy: validation

Validate before calling

if (clientOptions.getMode() == CopilotClientMode.EMPTY && resumeConfig.getAvailableTools() == null) {
    throw new IllegalArgumentException("EMPTY mode requires availableTools on resume config");
}

Try / catch

try {
    client.resumeSession(config);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("did not specify availableTools")) {
        config.setAvailableTools(new ToolSet().addBuiltIn(BuiltInTools.ISOLATED));
        client.resumeSession(config);
    }
}

Prevention

When it happens

Trigger: Calling resumeSession (or creating a resume request) on a client constructed with mode = EMPTY while the resume config's getAvailableTools() returns null.

Common situations: 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.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/538316626e8b8d26. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/CopilotClient.java:1150

                session.registerTransformCallbacks(extracted.transformCallbacks());
            }
            var request = SessionRequestBuilder.buildResumeRequest(sessionId, config, options.getMode());
            if (extracted.wireSystemMessage() != config.getSystemMessage()) {
                request.setSystemMessage(extracted.wireSystemMessage());
            }

            // Opt this session into GitHub telemetry forwarding when a
            // connection-level handler is registered (mirrors the runtime's
            // hand-written capability flag, not part of the codegen'd contract).
            if (options.getOnGitHubTelemetry() != null) {
                request.setEnableGitHubTelemetryForwarding(true);
            }

            // Empty mode: validate availableTools and set toolFilterPrecedence for resume
            // path
            if (options.getMode() == CopilotClientMode.EMPTY) {
                if (config.getAvailableTools() == null) {
                    throw new IllegalArgumentException(
                            "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)).");
                }
                request.setToolFilterPrecedence("excluded");
                if (request.getSkipEmbeddingRetrieval() == null) {
                    request.setSkipEmbeddingRetrieval(true);
                }
                if (request.getEmbeddingCacheStorage() == null) {
                    request.setEmbeddingCacheStorage("in-memory");
                }
                if (request.getEnableOnDemandInstructionDiscovery() == null) {
                    request.setEnableOnDemandInstructionDiscovery(false);
                }
                if (request.getEnableFileHooks() == null) {
                    request.setEnableFileHooks(false);
                }
                if (request.getEnableHostGitOperations() == null) {

View on GitHub (pinned to cd8cf15dc3)