{"record":{"id":"5afc23e83e530b2e","repo":"Budibase/budibase","slug":"provider-config-provider-not-found","errorCode":null,"errorMessage":"Provider ${config.provider} not found","messagePattern":"Provider (.+?) not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/api/controllers/ai/configs.ts","lineNumber":25,"sourceCode":"  PASSWORD_REPLACEMENT,\n  UserCtx,\n  AIConfigType,\n  RequiredKeys,\n  LLMProvidersResponse,\n  AIConfigResponse,\n  BUDIBASE_AI_PROVIDER_ID,\n} from \"@budibase/types\"\nimport sdk from \"../../../sdk\"\nimport { isEnvironmentVariableKey } from \"../../../sdk/utils\"\n\nconst sanitizeConfig = async (\n  config: CustomAIProviderConfig\n): Promise<AIConfigResponse> => {\n  const providers = await sdk.ai.configs.fetchLiteLLMProviders()\n  const provider = providers.find(p => p.id === config.provider)\n\n  if (!provider) {\n    throw new Error(`Provider ${config.provider} not found`)\n  }\n\n  const secretFields = provider.credentialFields\n    .filter(f => f.field_type === \"password\")\n    .map(f => f.key)\n  const credentialsFields = { ...config.credentialsFields }\n\n  for (const field of secretFields) {\n    if (\n      credentialsFields[field] &&\n      !isEnvironmentVariableKey(credentialsFields[field])\n    ) {\n      credentialsFields[field] = PASSWORD_REPLACEMENT\n    }\n  }\n\n  const sanitized: AIConfigResponse = {\n    ...config,","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/ai/configs.ts#L7-L43","documentation":"sanitizeConfig resolves the AI provider id stored on a CustomAIProviderConfig against the live list of LiteLLM providers (fetchLiteLLMProviders). If no provider with that id exists, it throws a plain Error. This runs on every read (fetchAIConfigs) and write (create/update), so it also surfaces when listing configs, not only when creating one.","triggerScenarios":"GET /api/ai/configs when a stored config references a provider id no longer registered in LiteLLM; POST/PUT with body.provider set to an unknown/stale provider id; LiteLLM provisioning changed so provider ids were renamed or removed.","commonSituations":"LiteLLM was redeployed/reprovisioned and provider ids changed; a config was created against a provider that was later deleted; typo in the provider id in an API call; environment's LiteLLM proxy not synced with the Budibase config database.","solutions":["Check the config's provider value and compare against ids returned by GET /api/ai/providers (fetchLiteLLMProviders).","Update the config (PUT) to point at an existing provider id, or delete the orphaned config.","Verify the LiteLLM proxy is running and its provider registry is loaded (providers endpoint returns data, not an empty list).","If provider ids changed after redeployment, migrate stored configs to the new ids in one pass.","For fresh setups, create the provider in LiteLLM before creating AI configs that reference it."],"exampleFix":"// before\nawait api.post(\"/api/ai/configs\", { name: \"gpt\", provider: \"openai-prod-v1\", ... })\n// after: use an id from the providers list\nconst providers = await api.get(\"/api/ai/providers\")\nawait api.post(\"/api/ai/configs\", { name: \"gpt\", provider: providers[0].id, ... })","handlingStrategy":"validation","validationCode":"const providers = await api.get(\"/api/ai/providers\")\nconst valid = providers.some(p => p.id === config.provider)\nif (!valid) throw new Error(`Provider ${config.provider} is not registered in LiteLLM`)","typeGuard":"const isKnownProvider = (providers: { id: string }[], id: string): id is string =>\n  providers.some(p => p.id === id)","tryCatchPattern":"try {\n  await api.post(\"/api/ai/configs\", config)\n} catch (e) {\n  if (String(e.message).includes(\"Provider\") && e.message.includes(\"not found\")) {\n    const providers = await api.get(\"/api/ai/providers\")\n    console.log(\"Valid provider ids:\", providers.map(p => p.id))\n  }\n}","preventionTips":["Resolve provider ids from the providers list, never hardcode them","Re-provision/migrate configs after LiteLLM redeploys that change provider ids","Delete orphaned configs that reference removed providers","Health-check the LiteLLM proxy before config operations"],"tags":["ai-configs","litellm","provider-not-found","http-500"],"backgroundTag":"provider-not-found","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}