getredash/redash · error

Can't delete built-in groups.

Error message

Can't delete built-in groups.

What it means

Raised by GroupResource.delete in redash/handlers/groups.py when attempting to delete a built-in group. Built-in groups (default, admin, etc.) anchor Redash's permission model and cannot be removed; attempting it returns 400.

Source

Thrown at redash/handlers/groups.py:61

        self.record_event({"action": "edit", "object_id": group.id, "object_type": "group"})

        return group.to_dict()

    def get(self, group_id):
        if not (self.current_user.has_permission("admin") or int(group_id) in self.current_user.group_ids):
            abort(403)

        group = models.Group.get_by_id_and_org(group_id, self.current_org)

        self.record_event({"action": "view", "object_id": group_id, "object_type": "group"})

        return group.to_dict()

    @require_admin
    def delete(self, group_id):
        group = models.Group.get_by_id_and_org(group_id, self.current_org)
        if group.type == models.Group.BUILTIN_GROUP:
            abort(400, message="Can't delete built-in groups.")

        members = models.Group.members(group_id)
        for member in members:
            member.group_ids.remove(int(group_id))
            models.db.session.add(member)

        models.db.session.delete(group)
        models.db.session.commit()


class GroupMemberListResource(BaseResource):
    @require_admin
    def post(self, group_id):
        user_id = request.json["user_id"]
        user = models.User.get_by_id_and_org(user_id, self.current_org)
        group = models.Group.get_by_id_and_org(group_id, self.current_org)
        user.group_ids.append(group.id)
        models.db.session.commit()

View on GitHub (pinned to ca79fe988d)

Solutions

  1. Filter out built-in groups before deleting; only custom groups can be removed.
  2. If you want built-in groups empty, remove their members instead of deleting the group.
  3. Assert group type != 'builtin' in test fixtures before delete calls.

Example fix

# before
client.delete(f"/api/groups/{group_id}")

# after
grp = client.get(f"/api/groups/{group_id}")
if grp['type'] != 'builtin':
    client.delete(f"/api/groups/{group_id}")
Defensive patterns

Strategy: validation

Validate before calling

g = client.get(f'/api/groups/{gid}')
if g['type'] != 'builtin':
    client.delete(f'/api/groups/{gid}')

Type guard

def is_deletable_group(group: dict) -> bool:
    return group.get('type') != 'builtin'

Prevention

When it happens

Trigger: DELETE /api/groups/<id> where the group's type is Group.BUILTIN_GROUP.

Common situations: Cleanup scripts deleting every group in an org; test teardown deleting groups created by fixtures but accidentally targeting built-ins; org provisioning scripts assuming all groups are deletable.

Related errors


AI-assisted analysis of getredash/redash@ca79fe988d (2026-08-28). Data as JSON: /api/errors/a80e3871e48bdf7b. Report an issue: GitHub.