Budibase/budibase · error · HTTPError
_id and _rev are required
Error message
_id and _rev are required
What it means
update persists changes to an existing agent document. CouchDB-style persistence requires both _id (document key) and _rev (current revision) for an update; if either is missing on the passed Agent object the function throws a 400 HTTPError before any DB access, preventing accidental document creation or revision conflicts.
Source
Thrown at packages/server/src/sdk/workspace/ai/agents/crud.ts:532
return await create({
name,
description: source.description,
aiconfig: source.aiconfig,
projectIds: await getValidProjectIdsForDuplication(source.projectIds),
goal: source.goal,
icon: source.icon,
iconColor: source.iconColor,
live: source.live,
_deleted: false,
createdBy,
operations: source.operations,
})
}
export async function update(agent: Agent): Promise<Agent> {
const { _id, _rev } = agent
if (!_id || !_rev) {
throw new HTTPError("_id and _rev are required", 400)
}
const db = context.getWorkspaceDB()
const existing = await getOrThrow(_id)
const incomingName = agent.name ?? existing.name
const normalizedName = helpers.normalizeForComparison(incomingName)
const normalizedExistingName = helpers.normalizeForComparison(existing.name)
if (normalizedName !== normalizedExistingName) {
await guardName(incomingName, _id)
}
const now = new Date().toISOString()
const incomingOperations = agent.operations ?? existing.operations ?? []
const removedOperations = (existing.operations ?? []).filter(
existingOperation =>
existingOperation.id &&View on GitHub (pinned to a81a902e9a)
Solutions
- Fetch the agent first (getOrThrow) and merge your changes onto the returned document so _id and _rev are present
- Check any serialization/HTTP layer for stripping or renaming the _id/_rev fields
- If you intended to create rather than update, call create instead
- Guard before calling: if (!agent._id || !agent._rev) fetch the doc first
Example fix
// before
await sdk.ai.agents.update({ ...changes })
// after
const existing = await sdk.ai.agents.getOrThrow(agentId)
await sdk.ai.agents.update({ ...existing, ...changes }) Defensive patterns
Strategy: validation
Validate before calling
if (!agent._id || !agent._rev) {
const existing = await sdk.ai.agents.getOrThrow(agentId)
agent = { ...existing, ...changes }
}
await sdk.ai.agents.update(agent) Type guard
function isPersistedAgent(a: Partial<Agent>): a is Agent & { _id: string; _rev: string } {
return typeof a._id === "string" && typeof a._rev === "string"
} Try / catch
try {
await sdk.ai.agents.update(agent)
} catch (err) {
if (err instanceof HTTPError && err.status === 400 && /_id and _rev/.test(err.message)) {
// re-fetch the doc and merge changes before updating
} else { throw err }
} Prevention
- Always fetch the agent first and spread changes onto the fetched doc
- Watch for serialization layers stripping _id/_rev
- Use create for new agents, update only for persisted documents
When it happens
Trigger: Calling update with an object that lacks _id or _rev — e.g. passing a newly constructed agent literal, a response from an API that stripped underscore fields, spreading a partial update over nothing, or client code that submitted a payload omitting the CouchDB metadata fields.
Common situations: Frontend sending only changed fields without merging them onto the fetched doc; serialization layers that camelCase/strip _id/_rev; constructing Agent objects manually for tests; attempting to 'update' an agent that was never fetched (no revision available).
Related errors
- Agent name is required.
- Agent with name '${name}' already exists.
- agentId is required
- Invalid bookmark query
- Invalid limit query
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/526ec34b2db12dd5.
Report an issue: GitHub.