Budibase/budibase · error · HTTPError

Workspace ID is required to configure LiteLLM

Error message

Workspace ID is required to configure LiteLLM

What it means

getKeySettings lazily provisions the workspace's LiteLLM virtual key. It derives the lock/resource scope from context.getProdWorkspaceId(); when there is no prod workspace ID in the execution context (e.g. running at the global/platform level or inside a bare tenant DB), it cannot scope the key and throws HTTP 400 instead of creating a malformed key.

Source

Thrown at packages/server/src/sdk/workspace/ai/configs/litellm.ts:390

  if (model.configType !== AIConfigType.COMPLETIONS) {
    throw new HTTPError(`Unsupported AI config type: ${model.configType}`, 400)
  }
  return validateCompletionsModel(model)
}

export async function getKeySettings(): Promise<{
  keyId: string
  secretKey: string
  teamId: string
}> {
  const db = context.getWorkspaceDB()
  const keyDocId = docIds.getLiteLLMKeyID()

  let keyConfig = await db.tryGet<LiteLLMKeyConfig>(keyDocId)
  if (!keyConfig || !keyConfig.teamId) {
    const workspaceId = context.getProdWorkspaceId()
    if (!workspaceId) {
      throw new HTTPError("Workspace ID is required to configure LiteLLM", 400)
    }
    const { result } = await locks.doWithLock(
      {
        name: LockName.LITELLM_KEY,
        type: LockType.AUTO_EXTEND,
        resource: workspaceId,
      },
      async () => {
        let existingKeyConfig = await db.tryGet<LiteLLMKeyConfig>(keyDocId)
        const shouldCreateTenantTeam = !existingKeyConfig?.teamId

        if (existingKeyConfig && !shouldCreateTenantTeam) {
          return existingKeyConfig
        }

        const team = await getOrCreateTenantTeam()

        if (existingKeyConfig) {

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Ensure the code runs inside a workspace context (context.withWorkspace / the request carries the app/workspace ID) before calling getKeySettings.
  2. Pass an explicit workspace ID to the surrounding operation so context.getProdWorkspaceId() resolves.
  3. For tests/scripts, wrap the call in the test helper that seeds prod workspace context.

Example fix

// before
await getKeySettings() // no workspace context
// after
await context.doInWorkspace(appId, async () => {
  await getKeySettings()
})
Defensive patterns

Strategy: validation

Validate before calling

import { context } from "@budibase/backend-core"
const wsId = context.getProdWorkspaceId()
if (!wsId) throw new Error("Call getKeySettings only inside a prod workspace context")

Try / catch

try {
  await getKeySettings()
} catch (e) {
  if (e.status === 400 && e.message.includes("Workspace ID is required")) {
    // re-run wrapped in workspace context
    return context.doInWorkspace(appId, getKeySettings)
  }
  throw e
}

Prevention

When it happens

Trigger: Calling getKeySettings (or code paths that call it: create/update of AI configs) while the request context has no production workspace — e.g. no workspace header/doc context, running against the global DB, or a job executing outside any app/workspace context.

Common situations: Background scripts or tests that call LiteLLM helpers without establishing workspace context (ctx/workflow context not set); AI config CRUD invoked from tenant-level admin endpoints.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/fc1735ecb7140724. Report an issue: GitHub.