github/copilot-sdk · error · ValueError

CopilotClient is in mode='empty' but create_session was…

Error message

CopilotClient is in mode='empty' but create_session was called without available_tools. Empty mode requires every session to explicitly opt into the tools it wants — e.g. ToolSet().add_builtin(BUILTIN_TOOLS_ISOLATED).

What it means

In mode='empty' every session must explicitly declare which tools it may use; there is no implicit default tool set. create_session (and resume_session) without available_tools is rejected so no session accidentally inherits tools in an isolated environment.

Solutions

  1. Pass available_tools=ToolSet().add_builtin(BUILTIN_TOOLS_ISOLATED).to_list() to create_session
  2. Build the explicit per-session ToolSet your tenant requires and pass it on every create/resume
  3. If sessions should not be restricted, switch the client back to a non-'empty' mode
  4. Wrap session creation in a helper that always injects the tool filter for empty mode

Example fix

// before
session = client.create_session()

// after
session = client.create_session(
    available_tools=ToolSet().add_builtin(BUILTIN_TOOLS_ISOLATED).to_list()
)
Defensive patterns

Strategy: validation

Validate before calling

if client.mode == "empty" and available_tools is None:
    raise ValueError("empty mode requires available_tools on every session")

Type guard

def session_call_is_valid(mode, available_tools) -> bool:
    return mode != "empty" or available_tools is not None

Try / catch

try:
    session = client.create_session()
except ValueError as e:
    if "without available_tools" in str(e):
        session = client.create_session(available_tools=default_tool_set().to_list())

Prevention

When it happens

Trigger: Calling client.create_session() or client.resume_session(...) on a CopilotClient constructed with mode='empty' without passing available_tools (it remains None) — checked in _require_available_tools_for_empty_mode.

Common situations: Code shared between default-mode and empty-mode clients calls create_session uniformly; examples written for the default mode are reused in isolated multi-tenant deployments; a refactor moved the client into empty mode but session-creation call sites were not updated.

Understand the failure class

Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at python/copilot/_mode.py:366

    is_uri_connection: bool,
) -> None:
    if mode != "empty":
        return
    if base_directory or session_fs_set or is_uri_connection:
        return
    raise ValueError(
        "CopilotClient(mode='empty') requires base_directory, session_fs, "
        "or a UriRuntimeConnection. Empty mode needs explicit per-tenant "
        "storage and won't fall back to ~/.copilot."
    )


def _require_available_tools_for_empty_mode(
    mode: CopilotClientMode | None,
    available_tools: list[str] | None,
) -> None:
    if mode == "empty" and available_tools is None:
        raise ValueError(
            "CopilotClient is in mode='empty' but create_session was called "
            "without available_tools. Empty mode requires every session to "
            "explicitly opt into the tools it wants — e.g. "
            "ToolSet().add_builtin(BUILTIN_TOOLS_ISOLATED)."
        )

View on GitHub (pinned to cd8cf15dc3)