microsoft/semantic-kernel · error · ValueError

Client cannot be None

Error message

Client cannot be None

What it means

Raised by AzureAIAgentThread.__init__ when the client argument is None. The thread delegates all operations (create/delete/messages) to an AIProjectClient, so a null client makes it non-functional. Thrown as a plain ValueError, not an agent exception, at construction time.

Source

Thrown at python/semantic_kernel/agents/azure_ai/azure_ai_agent.py:284

        client: AIProjectClient,
        messages: list[ThreadMessageOptions] | None = None,
        metadata: dict[str, str] | None = None,
        thread_id: str | None = None,
        tool_resources: "ToolResources | None" = None,
    ) -> None:
        """Initialize the Azure AI Agent Thread.

        Args:
            client: The Azure AI Project client.
            messages: The messages to initialize the thread with.
            metadata: The metadata for the thread.
            thread_id: The ID of the thread
            tool_resources: The tool resources for the thread.
        """
        super().__init__()

        if client is None:
            raise ValueError("Client cannot be None")

        self._client = client
        self._id = thread_id
        self._messages = messages or []
        self._metadata = metadata
        self._tool_resources = tool_resources

    @override
    async def _create(self) -> str:
        """Starts the thread and returns its ID."""
        try:
            response = await self._client.agents.threads.create(
                messages=self._messages,
                metadata=self._metadata,
                tool_resources=self._tool_resources,
            )
        except Exception as ex:
            raise AgentThreadOperationException(

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Pass a valid AIProjectClient instance to AzureAIAgentThread(client=...).
  2. Create the client via AzureAIAgent.create_client(credential, endpoint) first and reuse it for both the agent and the thread.
  3. Ensure the client is created once and shared rather than constructed conditionally.

Example fix

// before
thread = AzureAIAgentThread()  // client missing
// after
client = await AzureAIAgent.create_client(credential, endpoint)
thread = AzureAIAgentThread(client=client)
Defensive patterns

Strategy: type-guard

Validate before calling

from azure.ai.projects.aio import AIProjectClient
def assert_client(client):
    if not isinstance(client, AIProjectClient):
        raise TypeError('client must be an AIProjectClient')
    return client

Type guard

def is_valid_client(client) -> bool:
    return client is not None and isinstance(client, AIProjectClient)

Try / catch

try:
    thread = AzureAIAgentThread(client=client)
except ValueError as e:
    if 'Client cannot be None' in str(e):
        log.error('Create the AIProjectClient before constructing the thread')
    raise

Prevention

When it happens

Trigger: Instantiating AzureAIAgentThread(client=None) directly; constructing the thread from a factory that failed to capture self.client; calling construct_thread=lambda: AzureAIAgentThread() without the client argument.

Common situations: Building a custom thread subclass or factory and forgetting to forward the client; refactoring that moved client creation into a branch that returned None on a config error; tests that construct the thread without mocking a client.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/5d11ea7b1bdf7e35. Report an issue: GitHub.