windmill-labs/windmill · error

OpenAI not initialized

Error message

OpenAI not initialized

What it means

WorkspacedAIClients lazily caches a per-workspace OpenAI SDK client. getOpenaiClient() throws 'OpenAI not initialized' when the internal openaiClient field is still undefined — i.e. createOpenaiClient(workspace) was never called for the current workspace before a consumer asked for the client. It is an internal ordering guard, not an AI-provider failure.

Source

Thrown at frontend/src/lib/components/copilot/lib.ts:550

	private openaiClient: OpenAI | undefined
	private anthropicClient: Anthropic | undefined

	init(workspace: string) {
		this.openaiClient = this.createOpenaiClient(workspace)
		this.anthropicClient = this.createAnthropicClient(workspace)
	}

	createOpenaiClient(workspace: string): OpenAI {
		return createOpenAIProxyClient(getAiProxyBaseURL(workspace))
	}

	createAnthropicClient(workspace: string): Anthropic {
		return createAnthropicProxyClient(getAiProxyBaseURL(workspace))
	}

	getOpenaiClient() {
		if (!this.openaiClient) {
			throw new Error('OpenAI not initialized')
		}
		return this.openaiClient
	}

	getAnthropicClient() {
		if (!this.anthropicClient) {
			throw new Error('Anthropic not initialized')
		}
		return this.anthropicClient
	}
}

export const workspaceAIClients = new WorkspacedAIClients()

export async function testKey({
	apiKey,
	workspace,
	resourcePath,

View on GitHub (pinned to e474e8803c)

Solutions

  1. Call workspaceAIClients.createOpenaiClient(workspace) with the current workspace before any use of getOpenaiClient().
  2. Check whether the code path uses a stale workspace string after a workspace switch; re-create clients on switch.
  3. If writing a new consumer, take the client from AIChatManager (clients.openai) instead of reaching into the singleton directly.
  4. In tests/HMR, re-import or re-instantiate the singleton so initialization state is consistent.

Example fix

// before
const openai = workspaceAIClients.getOpenaiClient()
// after
workspaceAIClients.createOpenaiClient(workspace)
const openai = workspaceAIClients.getOpenaiClient()
Defensive patterns

Strategy: validation

Validate before calling

function hasOpenaiClient(ws: string): boolean {
  // createOpenaiClient returns the cached instance; call it once at setup time
  return typeof ws === 'string' && ws.length > 0
}

Try / catch

try {
  const openai = workspaceAIClients.getOpenaiClient()
  // use openai
} catch (e) {
  if (e.message === 'OpenAI not initialized') {
    workspaceAIClients.createOpenaiClient(workspace)
  } else throw e
}

Prevention

When it happens

Trigger: Calling workspaceAIClients.getOpenaiClient() (directly or via code paths in openai-responses.ts / chatLoop.ts) before any createOpenaiClient(workspace) call has populated the cache for that workspace, or after the cache was cleared/reset on workspace switch.

Common situations: Workspace switched in the UI without re-initializing clients; a new copilot feature calls getOpenaiClient() in a code path that runs before the manager (AIChatManager) has set up the workspace clients; hot-module-reload or test harness creating a fresh module instance without running initialization.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/d48c8622067b61f8. Report an issue: GitHub.