{"record":{"id":"0df50eb9f27c1874","repo":"Budibase/budibase","slug":"key-already-exists-cannot-be-recreated","errorCode":null,"errorMessage":"Key already exists, cannot be recreated","messagePattern":"Key already exists, cannot be recreated","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/configs/litellm.ts","lineNumber":566,"sourceCode":"      modelIds,\n    })\n    success = true\n  } catch (err: any) {\n    if (!isMissingVirtualKeyError(err)) {\n      throw err\n    }\n  }\n\n  if (!success) {\n    const keyRes = await fetch(`${liteLLMUrl}/key/info?key=${keyId}`, {\n      method: \"GET\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        Authorization: liteLLMAuthorizationHeader,\n      },\n    })\n    if (keyRes.status !== 404) {\n      throw new Error(\"Key already exists, cannot be recreated\")\n    }\n\n    const regeneratedKey = await regenerateWorkspaceKey()\n    keyId = regeneratedKey.keyId\n    await updateKey({\n      keyId,\n      modelIds,\n    })\n  }\n}\n\ntype LiteLLMPublicProvider = {\n  provider: string\n  provider_display_name: string\n  litellm_provider: string\n  default_model_placeholder?: string | null\n  credential_fields: {\n    key: string","sourceCodeStart":548,"sourceCodeEnd":584,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/configs/litellm.ts#L548-L584","documentation":"syncKeyModels only recreates the LiteLLM key when the key-status probe returns exactly 404 (key missing). Any other response (200/401/500) means the key still exists or the check could not confirm deletion, so recreating would duplicate it; it throws this plain Error to abort the sync.","triggerScenarios":"Calling syncKeyModels (via create/update/remove/reconcileLiteLLMModels) after a key deletion that did not actually propagate on the LiteLLM side, or when the status probe fails with non-404 (auth error, network 5xx) while the code path assumed a missing key.","commonSituations":"Key deleted in the Budibase DB but not in LiteLLM (partial deletion); LiteLLM returning 401 so the 404 check fails; race where another process recreated the key between removal and sync.","solutions":["Delete the existing virtual key in LiteLLM (or confirm its 404) before re-running syncKeyModels.","Fix any auth/proxy issue causing the status probe to return non-404 (check master key, proxy health).","Remove the stale LiteLLM key doc or re-run reconcileLiteLLMModels so deletion and recreation complete atomically."],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"// confirm the key is really gone in LiteLLM before re-syncing\nconst res = await fetch(keyStatusUrl, { headers: { Authorization: authHeader } })\nif (res.status !== 404) throw new Error(\"Key still exists upstream — delete it before re-creating\")","typeGuard":null,"tryCatchPattern":"try {\n  await syncKeyModels(keyId, models)\n} catch (e) {\n  if (e.message === \"Key already exists, cannot be recreated\") {\n    await deleteLiteLLMKey(keyId) // remove upstream, then retry\n    await syncKeyModels(keyId, models)\n  } else throw e\n}","preventionTips":["Make key deletion verify upstream 404 before finishing.","Use the LITELLM_KEY lock for all delete/recreate flows to avoid races.","Investigate non-404 status probe results (auth errors) instead of skipping deletion."],"tags":["litellm","key-management","state-conflict","race-condition"],"backgroundTag":"resource-already-exists","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}