{"record":{"id":"bfb2661f9245d3f9","repo":"Budibase/budibase","slug":"unsupported-ai-config-type-model-configtype","errorCode":null,"errorMessage":"Unsupported AI config type: ${model.configType}","messagePattern":"Unsupported AI config type: (.+?)","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/configs/litellm.ts","lineNumber":373,"sourceCode":"    const message = [\n      \"Error validating configuration\",\n      sanitizeLiteLLMErrorMessage(json.error?.message || json.result?.error),\n    ]\n      .filter(Boolean)\n      .join(\": \")\n\n    throw new HTTPError(message, 400)\n  }\n}\n\nexport async function validateConfig(model: {\n  provider: string\n  name: string\n  credentialFields: Record<string, string>\n  configType: AIConfigType\n}) {\n  if (model.configType !== AIConfigType.COMPLETIONS) {\n    throw new HTTPError(`Unsupported AI config type: ${model.configType}`, 400)\n  }\n  return validateCompletionsModel(model)\n}\n\nexport async function getKeySettings(): Promise<{\n  keyId: string\n  secretKey: string\n  teamId: string\n}> {\n  const db = context.getWorkspaceDB()\n  const keyDocId = docIds.getLiteLLMKeyID()\n\n  let keyConfig = await db.tryGet<LiteLLMKeyConfig>(keyDocId)\n  if (!keyConfig || !keyConfig.teamId) {\n    const workspaceId = context.getProdWorkspaceId()\n    if (!workspaceId) {\n      throw new HTTPError(\"Workspace ID is required to configure LiteLLM\", 400)\n    }","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/configs/litellm.ts#L355-L391","documentation":"validateConfig is the gatekeeper for AI config creation/update against LiteLLM. It only supports configs whose configType is AIConfigType.COMPLETIONS; any other (unknown or future) config type is rejected with HTTP 400 before delegating to validateCompletionsModel. The enum (packages/types/src/documents/global/ai.ts) currently only contains COMPLETIONS, so this fires when a caller supplies a mistyped, stale, or invented configType string.","triggerScenarios":"POST/PUT to the AI config endpoints (create/update in sdk/workspace/ai/configs/index.ts) with body.configType set to anything other than \"completions\" — e.g. \"completion\" (typo), \"chat\", \"embedding\", or a value from an older client.","commonSituations":"Hand-rolled API calls to the configs endpoint with a wrong configType; a client SDK or script written against an older/preview enum; copying config JSON between environments where the type drifted.","solutions":["Set configType to \"completions\" in the request body (or omit it where the controller defaults it to AIConfigType.COMPLETIONS).","Check the exact enum value in @budibase/types (AIConfigType) rather than guessing the string.","If a genuinely new config type is needed, extend AIConfigType and add a matching validator in validateConfig."],"exampleFix":"// before\nawait api.post(\"/ai/configs\", { name: \"gpt4o\", configType: \"chat\", ... })\n// after\nawait api.post(\"/ai/configs\", { name: \"gpt4o\", configType: \"completions\", ... })","handlingStrategy":"validation","validationCode":"const ALLOWED = [\"completions\"]\nif (!ALLOWED.includes(config.configType)) {\n  throw new Error(`configType must be one of ${ALLOWED.join(\", \")}, got ${config.configType}`)\n}","typeGuard":"function isCompletionsConfig(c: { configType: string }): c is { configType: \"completions\" } {\n  return c.configType === \"completions\"\n}","tryCatchPattern":"try {\n  await createConfig(cfg)\n} catch (e) {\n  if (e.status === 400 && e.message.startsWith(\"Unsupported AI config type\")) {\n    cfg.configType = \"completions\"\n    await createConfig(cfg)\n  } else throw e\n}","preventionTips":["Always send configType: \"completions\" (or omit it to use the server default).","Import AIConfigType from @budibase/types instead of hardcoding strings.","Validate payload against the API schema before POST/PUT."],"tags":["validation","http-400","ai-config","enum"],"backgroundTag":"unsupported-config-type","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}