getredash/redash · error

Group id {} is invalid.

Error message

Group id {} is invalid.

What it means

Raised by the user update endpoint when the request's group_ids array references a group that does not exist within the current organization. The handler verifies each id via models.Group.get_by_id_and_org and aborts with HTTP 400 on the first id that yields NoResultFound.

Source

Thrown at redash/handlers/users.py:232

        if "password" in params and "old_password" not in params:
            abort(403, message="Must provide current password to update password.")

        if "old_password" in params and not user.verify_password(params["old_password"]):
            abort(403, message="Incorrect current password.")

        if "password" in params:
            user.hash_password(params.pop("password"))
            params.pop("old_password")

        if "group_ids" in params:
            if not self.current_user.has_permission("admin"):
                abort(403, message="Must be admin to change groups membership.")

            for group_id in params["group_ids"]:
                try:
                    models.Group.get_by_id_and_org(group_id, self.current_org)
                except NoResultFound:
                    abort(400, message="Group id {} is invalid.".format(group_id))

            if len(params["group_ids"]) == 0:
                params.pop("group_ids")

        if "email" in params:
            require_allowed_email(params["email"])

        email_address_changed = "email" in params and params["email"] != user.email
        needs_to_verify_email = email_address_changed and settings.email_server_is_configured()
        if needs_to_verify_email:
            user.is_email_verified = False

        try:
            self.update_model(user, params)
            models.db.session.commit()

            if needs_to_verify_email:
                send_verify_email(user, self.current_org)

View on GitHub (pinned to ca79fe988d)

Solutions

  1. Fetch valid ids first via GET /api/groups and use ids from that response
  2. Verify each id exists in the same organization as the user being edited
  3. Drop deleted/stale ids from group_ids before resubmitting

Example fix

# before
{"group_ids": [1, 999]}  # 400: Group id 999 is invalid.
# after
groups = requests.get(f"{url}/api/groups", headers=hdrs).json()
valid = {g["id"] for g in groups}
{"group_ids": [g for g in [1, 999] if g in valid]}
Defensive patterns

Strategy: validation

Validate before calling

valid = {g["id"] for g in requests.get(f"{url}/api/groups", headers=hdrs).json()}
payload["group_ids"] = [gid for gid in payload.get("group_ids", []) if gid in valid]
if not payload["group_ids"]:
    payload.pop("group_ids", None)

Type guard

def is_valid_group_id(groups, gid):
    return isinstance(gid, int) and gid in {g["id"] for g in groups}

Prevention

When it happens

Trigger: POST to /api/users/<id> with group_ids containing an id that is deleted, belongs to a different organization, or is a plain typo (e.g. [999]); passing group names or slugs instead of numeric ids also produces it.

Common situations: Stale cached group lists after groups were deleted or re-created; scripts copy-pasting group ids between environments (staging vs prod orgs); sending strings like "group_admin" instead of the numeric id.

Related errors


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