{"record":{"id":"c289623843b462ef","repo":"Budibase/budibase","slug":"config-id-is-required","errorCode":null,"errorMessage":"Config ID is required","messagePattern":"Config ID is required","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/api/controllers/ai/configs.ts","lineNumber":152,"sourceCode":"    model: body.model,\n\n    webSearchConfig: body.webSearchConfig,\n    configType,\n    reasoningEffort: body.reasoningEffort,\n    isDefault: body.isDefault,\n  }\n\n  const updatedConfig = await sdk.ai.configs.update(updateRequest)\n\n  ctx.body = await sanitizeConfig(updatedConfig)\n}\n\nexport const deleteAIConfig = async (\n  ctx: UserCtx<{ id: string }, { deleted: true }>\n) => {\n  const { id } = ctx.params\n  if (!id) {\n    throw new HTTPError(\"Config ID is required\", 400)\n  }\n\n  await sdk.ai.configs.remove(id)\n\n  ctx.body = { deleted: true }\n}\n","sourceCodeStart":134,"sourceCodeEnd":159,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/ai/configs.ts#L134-L159","documentation":"deleteAIConfig reads the config id from the route params and refuses to call sdk.ai.configs.remove when it is absent, returning 400 'Config ID is required'. This guards against routing misconfiguration or calls made to the base path without an id segment.","triggerScenarios":"DELETE to the ai configs route without an id path parameter (route hit at collection level), or an id that is empty/undefined due to template interpolation of an undefined variable in the client URL.","commonSituations":"Client code building the URL with an undefined config id (`/api/ai/configs/${id}` where id is undefined); router misconfiguration matching the delete handler to the collection route; deleting after an optimistic local removal that already cleared the id from state.","solutions":["Ensure the DELETE request targets /api/ai/configs/:id with a real id in the URL.","Log/inspect the URL before sending; guard client code against undefined ids before issuing the request.","Remove the config from local state only after a successful DELETE response.","If ids come from a list, ensure the item's _id (not a UI-only index) is used in the path."],"exampleFix":"// before\nconst id = selected?._id\nawait api.delete(`/api/ai/configs/${id}`) // id may be undefined -> /api/ai/configs/undefined\n// after\nif (!selected?._id) return\nawait api.delete(`/api/ai/configs/${selected._id}`)","handlingStrategy":"type-guard","validationCode":"if (typeof configId !== \"string\" || !configId) {\n  throw new Error(\"Cannot delete AI config without an id\")\n}\nawait api.delete(`/api/ai/configs/${configId}`)","typeGuard":"const isNonEmptyString = (v: unknown): v is string =>\n  typeof v === \"string\" && v.length > 0","tryCatchPattern":"try {\n  await api.delete(`/api/ai/configs/${id}`)\n} catch (e) {\n  if (e.status === 400 && e.message.includes(\"Config ID is required\")) {\n    // URL was built with a missing/undefined id — do not remove from local state\n  }\n}","preventionTips":["Guard client code before interpolating ids into URLs","Only clear local state after a successful delete response","Verify route wiring maps the delete handler to /:id, not the collection path","Use resource _id, not list indices, for delete calls"],"tags":["http-400","validation","ai-configs","missing-path-param"],"backgroundTag":"missing-required-field","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}