getredash/redash · error

Can't modify built-in groups.

Error message

Can't modify built-in groups.

What it means

Raised by GroupResource.post in redash/handlers/groups.py when an admin tries to rename a built-in group (type == Group.BUILTIN_GROUP, i.e. the default/admin/limited built-in groups). Built-in groups' names are fixed by Redash and cannot be edited.

Source

Thrown at redash/handlers/groups.py:38

    def get(self):
        if self.current_user.has_permission("admin"):
            groups = models.Group.all(self.current_org)
        else:
            groups = models.Group.query.filter(models.Group.id.in_(self.current_user.group_ids))

        self.record_event({"action": "list", "object_id": "groups", "object_type": "group"})

        return [g.to_dict() for g in groups]


class GroupResource(BaseResource):
    @require_admin
    def post(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 modify built-in groups.")

        group.name = request.json["name"]
        models.db.session.commit()

        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()

View on GitHub (pinned to ca79fe988d)

Solutions

  1. Skip groups whose type is 'builtin' in any rename automation; create a new custom group instead.
  2. If a different name is needed, create a new group with the desired name and move members.
  3. Check group type via GET /api/groups/<id> before posting changes.

Example fix

# before
for g in client.get('/api/groups')['results']:
    client.post(f"/api/groups/{g['id']}", json={'name': new_name})

# after
for g in client.get('/api/groups')['results']:
    if g['type'] != 'builtin':
        client.post(f"/api/groups/{g['id']}", json={'name': new_name})
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Prevention

When it happens

Trigger: POST /api/groups/<id> with {"name": ...} where <id> identifies a built-in group such as 'default' or 'admin' in that org.

Common situations: Automated group-management scripts iterating all groups and attempting renames; admin UI attempts to reorganize built-in groups into a naming scheme.

Related errors


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