Budibase/budibase · error

Failed to refresh saved group

Error message

Failed to refresh saved group

What it means

When saving a group marked as default, setting a default has side effects on other groups, so the store re-fetches all groups and returns the refreshed saved group. If the just-saved group cannot be found in the fresh list, it throws — meaning the server response doesn't include the group, indicating a sync or API inconsistency.

Source

Thrown at packages/builder/src/stores/portal/groups.ts:62

  private async refreshGroup(groupId: string) {
    const group = await API.getGroup(groupId)
    this.updateStore(group)
  }

  async save(group: UserGroup) {
    const { ...dataToSave } = group
    delete dataToSave.scimInfo
    const response = await API.saveGroup(dataToSave)
    group._id = response._id
    group._rev = response._rev

    // Setting a default group has side effects on other groups, so refresh all.
    if (group.isDefault) {
      const latestGroups = await API.getGroups()
      this.set(latestGroups)
      const savedGroup = latestGroups.find(g => g._id === group._id)
      if (!savedGroup) {
        throw new Error("Failed to refresh saved group")
      }
      return savedGroup
    }

    this.updateStore(group)
    return group
  }

  async delete(group: UserGroup) {
    await API.deleteGroup(group._id!, group._rev!)
    this.update(groups => {
      const index = groups.findIndex(g => g._id === group._id)
      if (index !== -1) {
        groups.splice(index, 1)
      }
      return groups
    })
  }

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Re-fetch groups and verify the group still exists; retry the save if transient
  2. Check the save API call actually succeeded (inspect its response for errors)
  3. Verify the group's _id matches what the list endpoint returns (no id transformation)
  4. If the group was deleted concurrently, refresh the UI instead of retrying

Example fix

// before
const saved = await groups.save({ ...group, isDefault: true })
// after
try {
  const saved = await groups.save({ ...group, isDefault: true })
} catch {
  await groups.fetch()
}
Defensive patterns

Strategy: try-catch

Validate before calling

const list = await API.getGroups()
if (!list.some(g => g._id === group._id)) {
  // group is gone or save failed — resync before saving
}

Try / catch

try {
  const saved = await groups.save({ ...group, isDefault: true })
} catch (e) {
  if (e.message === "Failed to refresh saved group") {
    await groups.fetch()
    // surface a refresh/exists message to the user
  } else throw e
}

Prevention

When it happens

Trigger: Saving a group with isDefault=true where the subsequent API.getGroups() response does not contain a group with the saved _id — e.g. the group was deleted server-side during the save, the save silently failed server-side, or the _id changed.

Common situations: Concurrent deletion of the group by another admin; backend filter excluding the group from the list response; id mismatch between save response and list items; multi-user admin sessions racing on default-group changes.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/2981b32b54d9a24c. Report an issue: GitHub.