Files
coder/site
Jake Howell a3a0079bd2 fix(site): stop redundant RBAC paywall error toast on Groups page (#28249)
> 🤖 This PR was written by Coder Agents on behalf of Jake Howell.

Fixes coder/coder#23898 / coder/coder#23898.

## Problem

On a deployment without a Premium license, opening **Admin → Deployment
settings → Groups** shows the Premium paywall *and* a redundant error
toast in the bottom-right reading "Template RBAC is a Premium feature.
Contact sales!".

## Root cause

`GroupsPage.tsx` fired the paginated `groupsByOrganization` query
unconditionally. Groups are gated behind the `template_rbac` (Premium)
entitlement, so the request returned `403` ("Template RBAC is a Premium
feature"), which a `useEffect` surfaced via `toast.error`. Meanwhile
`GroupsPageView` already renders `PaywallPremium` when `groupsEnabled`
is false, hence the duplicate messaging. The AI Governance page doesn't
fire an entitlement-gated request, so it only shows the paywall.

There's a second subtlety that made the bug load-path dependent:
`selectFeatureVisibility` returns `{}` when unlicensed, so
`template_rbac` is `undefined`, not `false`. React Query treats
`enabled: undefined` as enabled, so a naive `enabled: groupsEnabled &&
...` gate still fired the request on a fresh full page load (where
entitlements were briefly in flight). Client-side navigation happened to
have entitlements cached as `false`, so it looked fixed there but
reproduced on hard reload.

## Fix

Gate the groups query with `enabled: Boolean(groupsEnabled &&
organization)`. The `Boolean()` coercion is load-bearing: it turns the
`undefined` entitlement into a real `false` so the request is genuinely
skipped rather than defaulting to enabled. When the entitlement is
missing there is no request, no error, and the paywall remains the
single source of truth. Legitimate load failures (when the feature *is*
entitled) still toast as before.

<details><summary>Investigation notes</summary>

* `site/src/pages/GroupsPage/GroupsPage.tsx` — `groupsQuery` ran
regardless of entitlement; the `groupsQuery.error` effect calls
`toast.error`.
* `site/src/pages/GroupsPage/GroupsPageView.tsx` — renders
`PaywallPremium` when `!groupsEnabled`, independent of the query.
* `site/src/modules/dashboard/entitlements.ts` — `getFeatureVisibility`
returns `{}` when `!hasLicense`, so feature flags are `undefined` (not
`false`) on unlicensed deployments.
* `usePaginatedQuery` forwards `enabled` to the underlying `useQuery`,
and its prefetch / invalid-page effects are no-ops while the query is
disabled.
* Backend source of the message: `enterprise/coderd/templates.go`.

</details>

## Testing

Verified end-to-end on a local unlicensed `scripts/develop.sh`
deployment (the exact repro condition):

* Confirmed `GET /api/v2/organizations/coder/paginated-groups` returns
`403 "Template RBAC is a Premium feature. Contact sales!"` — the toast's
text.
* **Before fix:** hard reload of `/deployment/groups` shows the error
toast bottom-right alongside the paywall.
* **After fix:** 3 consecutive hard reloads, no toast at any point
(including the \~3s mark where it previously fired); paywall still
renders correctly.
* `pnpm --dir site lint:types` passes.

Before/after screenshots are attached in the PR thread / chat.
2026-08-18 14:14:30 +00:00
..