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
- Pass available_tools=ToolSet().add_builtin(BUILTIN_TOOLS_ISOLATED).to_list() to create_session
- Build the explicit per-session ToolSet your tenant requires and pass it on every create/resume
- If sessions should not be restricted, switch the client back to a non-'empty' mode
- 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
- Route all session creation through a helper that always passes available_tools
- Define a module-level DEFAULT_EMPTY_MODE_TOOLS constant and reuse it
- Update session-creation call sites whenever a client switches to mode='empty'
- Check the client mode in tests that exercise create_session/resume_session
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
- Invalid entry '*': there is no bare wildcard. Use `new…
- CopilotClient is in Mode = CopilotClientMode.Empty but the…
- invalid tool name: must not be empty
- invalid tool name : tool names must match…
- tool filter must be a ToolSet or list[str], not str. Pass a…
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)