Budibase/budibase · error · HTTPError
Config ID is required for updates
Error message
Config ID is required for updates
What it means
updateAIConfig performs a CouchDB-style document update and therefore requires the document _id on the body. Without _id it cannot identify which config to update, so it returns 400 'Config ID is required for updates'.
Source
Thrown at packages/server/src/api/controllers/ai/configs.ts:113
webSearchConfig: body.webSearchConfig,
configType: body.configType,
reasoningEffort: body.reasoningEffort,
isDefault: body.isDefault,
}
const newConfig = await sdk.ai.configs.create(createRequest)
ctx.body = await sanitizeConfig(newConfig)
}
export const updateAIConfig = async (
ctx: UserCtx<UpdateAIConfigRequest, AIConfigResponse>
) => {
const body = ctx.request.body
if (!body._id) {
throw new HTTPError("Config ID is required for updates", 400)
}
if (!body._rev) {
throw new HTTPError("Revision is required for updates", 400)
}
if (!body.name) {
throw new HTTPError("Config name is required", 400)
}
const configType = body.configType ?? AIConfigType.COMPLETIONS
const updateRequest: RequiredKeys<
RequiredKeys<Parameters<typeof sdk.ai.configs.update>[0]>
> = {
_id: body._id,
_rev: body._rev,
name: body.name,View on GitHub (pinned to a81a902e9a)
Solutions
- Include the config's _id in the PUT body (fetch the config first if needed).
- Preserve CouchDB metadata (_id, _rev) when transforming/submitting config objects.
- Use POST /api/ai/configs to create new configs instead of PUT.
- If the id is only known as a route param, merge it into the body before sending.
Example fix
// before
await api.put("/api/ai/configs", { name: "Renamed", _rev: config._rev })
// after
await api.put("/api/ai/configs", { _id: config._id, _rev: config._rev, name: "Renamed" }) Defensive patterns
Strategy: validation
Validate before calling
if (!config._id) throw new Error("Config _id is required before calling update") Type guard
const hasId = (c: { _id?: string }): c is { _id: string } =>
typeof c._id === "string" && c._id.length > 0 Try / catch
try {
await api.put("/api/ai/configs", body)
} catch (e) {
if (e.status === 400 && e.message.includes("Config ID is required")) {
// fetch the config by some external key, merge _id/_rev, retry
}
} Prevention
- Always fetch the existing config before updating so CouchDB metadata is present
- Never strip _id/_rev from documents before PUT
- Use create (POST) for new docs, update (PUT) only for existing docs
- Model update payloads as full document types, not partials
When it happens
Trigger: PUT /api/ai/configs with a body lacking _id (e.g. posting a create-shaped payload to the update endpoint); _id lost after stripping document metadata when cloning a config.
Common situations: Client fetches a config, deletes all CouchDB meta fields, then PUTs it back; API consumers confuse the create and update endpoints; mapping the body through a narrower type that drops _id.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Config name is required
- Config ID is required
- Cannot store document without _id field.
- Invalid bookmark query
- Invalid limit query
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/51dab358c987c2a2.
Report an issue: GitHub.