github/copilot-sdk · error · ValueError

CopilotClient(mode='empty') requires base_directory…

Error message

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.

What it means

CopilotClient with mode='empty' provides no default storage: it is designed for per-tenant isolation and will not fall back to the shared ~/.copilot directory. Construction therefore fails unless the caller supplies explicit storage via base_directory, a session_fs config, or a UriRuntimeConnection.

Solutions

  1. Pass base_directory='/path/to/tenant/storage' to CopilotClient
  2. Or provide a session_fs config (see _validate_session_fs_config for its required fields)
  3. Or supply a UriRuntimeConnection if storage is managed externally
  4. If you do not need isolation, keep the default mode instead of mode='empty'

Example fix

// before
client = CopilotClient(mode="empty")

// after
client = CopilotClient(mode="empty", base_directory=f"/data/tenants/{tenant_id}")
Defensive patterns

Strategy: validation

Validate before calling

if mode == "empty" and not (base_directory or session_fs or uri_connection):
    raise ValueError("mode='empty' requires base_directory, session_fs, or UriRuntimeConnection")

Type guard

def empty_mode_has_storage(**kwargs) -> bool:
    return bool(kwargs.get("base_directory") or kwargs.get("session_fs") or kwargs.get("uri_connection"))

Try / catch

try:
    client = CopilotClient(mode="empty")
except ValueError as e:
    if "requires base_directory" in str(e):
        client = CopilotClient(mode="empty", base_directory=default_tenant_dir())

Prevention

When it happens

Trigger: CopilotClient(mode='empty') constructed with no base_directory, no session_fs config, and no URI runtime connection — i.e. none of base_directory/session_fs_set/is_uri_connection is truthy in _require_storage_for_empty_mode during __init__.

Common situations: Developers switch from the default/'copilot-cli' mode to mode='empty' for multi-tenant use and forget that all default storage is disabled; sample code copied from default-mode docs omits the storage arguments.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at python/copilot/_mode.py:354

    if manage_schedule_enabled is not None:
        patch["manageScheduleEnabled"] = manage_schedule_enabled
    if included_builtin_skills is not None:
        patch["includedBuiltinSkills"] = included_builtin_skills
    return patch or None


def _require_storage_for_empty_mode(
    *,
    mode: CopilotClientMode | None,
    base_directory: str | None,
    session_fs_set: bool,
    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)