Budibase/budibase · error
Unable to remove doc without a valid _id and _rev.
Error message
Unable to remove doc without a valid _id and _rev.
What it means
remove deletes a document by _id and _rev; CouchDB requires both. When called with an object lacking _id/_rev or an id string without a rev, the wrapper refuses to issue the delete and throws, avoiding guaranteed CouchDB failures.
Source
Thrown at packages/backend-core/src/db/couch/DatabaseImpl.ts:282
return rows.map(row => (includeDocs ? row.doc! : row.value))
}
async remove(idOrDoc: string | Document, rev?: string) {
// not a read call - but don't create a DB to delete a document
return this.performCall(db => {
let _id: string
let _rev: string
if (isDocument(idOrDoc)) {
_id = idOrDoc._id!
_rev = idOrDoc._rev!
} else {
_id = idOrDoc
_rev = rev!
}
if (!_id || !_rev) {
throw new Error("Unable to remove doc without a valid _id and _rev.")
}
return () => db.destroy(_id, _rev)
})
}
async bulkRemove(documents: Document[], opts?: { silenceErrors?: boolean }) {
const response: Nano.DocumentBulkResponse[] = await this.performCall(db => {
return () =>
db.bulk({
docs: documents.map(doc => ({
...doc,
_deleted: true,
})),
})
})
if (opts?.silenceErrors) {
return
}View on GitHub (pinned to a81a902e9a)
Solutions
- Fetch the doc first (db.get) to obtain _id and _rev, then remove it
- Pass the rev explicitly: db.remove(id, rev)
- Validate the doc shape before calling remove
Example fix
// before await db.remove(doc) // doc may lack _rev // after const existing = await db.get(doc._id) await db.remove(existing._id, existing._rev)
Defensive patterns
Strategy: validation
Validate before calling
const canRemove = (doc: Document): doc is Document & { _id: string; _rev: string } =>
typeof doc._id === "string" && typeof doc._rev === "string"
if (!canRemove(doc)) throw new Error("doc needs _id and _rev before remove")
await db.remove(doc) Type guard
const isRemovable = (d: Document): d is Document & { _id: string; _rev: string } =>
!!(d as any)._id && !!(d as any)._rev Try / catch
try {
await db.remove(doc)
} catch (err) {
if (err.message.includes("without a valid _id and _rev")) {
const existing = await db.get(doc._id)
await db.remove(existing)
} else throw err
} Prevention
- Always db.get a doc before removing to guarantee a fresh _rev
- Avoid round-tripping docs through serialization that drops _rev
- Prefer remove(id, rev) with explicit arguments
When it happens
Trigger: remove(doc) where doc has no _rev (fetched without revs or constructed in memory), or remove(id) without the rev argument (undefined/null rev).
Common situations: Docs built client-side without revs, using stale objects whose _rev was stripped by serialization, forgetting to pass rev when calling remove(id, rev).
Related errors
- Cannot store document without _id field.
- Query ID or Revision is missing
- Revision is required for updates
- actionType ${query.extra.actionType} does not exist on DB fo
- _id or _rev fields missing
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/e2b32618ede10baa.
Report an issue: GitHub.