Budibase/budibase · error
User ID or revision missing
Error message
User ID or revision missing
What it means
In assignExistingUsersToWorkspace, after resolving groups the code needs both user._id and a current _rev to call users.addUserToWorkspace. If either is missing (the user vanished, or the fetched document has no revision) it throws 'User ID or revision missing'. _rev is required for optimistic-concurrency document updates.
Source
Thrown at packages/builder/src/settings/pages/people/users/workspaceInviteUtils.ts:284
rev = saved?._rev || rev
}
if (!user._id) {
throw new Error("User ID missing")
}
if (groupIdsToAdd.length) {
await Promise.all(
groupIdsToAdd.map(groupId => groupStore.addUser(groupId, user._id!))
)
}
if (!role) {
return email
}
if (groupIdsToAdd.length || !rev) {
const loaded = await users.get(user._id)
rev = loaded?._rev
}
if (!user._id || !rev) {
throw new Error("User ID or revision missing")
}
await users.addUserToWorkspace(user._id, role, rev)
return email
}
)
)
const assignedUsers = assignmentResults
.filter(
(result): result is PromiseFulfilledResult<string> =>
result.status === "fulfilled"
)
.map(result => result.value)
const addedToWorkspaceEmails = [...groupManagedUsers, ...assignedUsers]
return {
usersToInvite,
addedToWorkspaceEmails,View on GitHub (pinned to a81a902e9a)
Solutions
- Re-fetch the user before assignment to get a fresh _id/_rev and retry.
- Verify the user still exists and the current user has permission to read it.
- Check the users.get/users.save responses actually include _rev and surface API errors instead of continuing with undefined.
Example fix
// before
if (!user._id || !rev) { throw new Error("User ID or revision missing") }
// after
const fresh = await users.get(user._id)
if (!fresh?._id || !fresh?._rev) { return null } // skip missing/deleted users instead of failing the whole batch Defensive patterns
Strategy: try-catch
Validate before calling
const withIds = users.filter(u => !!u._id) const revs = await Promise.all(withIds.map(u => users.get(u._id!).then(l => l?._rev))) const ready = withIds.filter((u, i) => !!revs[i])
Type guard
const canAssign = (u: Partial<User>, rev?: string): u is User & { _id: string } =>
typeof u._id === "string" && typeof rev === "string" && rev.length > 0 Try / catch
try {
await users.addUserToWorkspace(user._id, role, rev)
} catch (e) {
if (e.message === "User ID or revision missing") {
console.warn(`Skipping user ${user.email}: deleted or unreadable`)
return null
}
throw e
} Prevention
- Re-fetch the user immediately before workspace assignment to get a fresh _rev.
- Treat missing _rev as 'user deleted concurrently' and skip rather than fail the batch.
- Check users.get responses for errors/undefined before proceeding.
When it happens
Trigger: user._id exists but the rev lookup failed: groupIdsToAdd.length > 0 or rev was falsy, so users.get(user._id) was called and returned undefined or a doc without _rev — e.g. the user was deleted concurrently or the get API returned an error object.
Common situations: Concurrent deletion of the user by another admin; the earlier users.save call returned a response without _rev; permission issues preventing the user fetch; stale user objects after another tab saved changes.
Related errors
- User revision missing
- User ID missing
- Cannot render an empty flow chain
- Source table '${relationship.sourceTable}' not found in data
- Target table '${relationship.targetTable}' not found in data
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/f9df95dce44896e7.
Report an issue: GitHub.