antiwork/gumroad · warning · Pundit::NotAuthorizedError

Your current role as #

Error message

Your current role as #{team_membership.role.humanize} cannot perform this action.

What it means

The role-specific sibling of error 293: build_error_message found a team membership for the signed-in user on the current seller, so the denial names their role — "Your current role as Admin/Marketing/Analyst cannot perform this action." Delivered by default_user_not_authorized as a 401 JSON body or a flash alert plus dashboard redirect. It means the user is authenticated and on the team, but their role's permissions do not cover this policy query.

Solutions

  1. Compare the user's membership role for the seller against the policy's permitted roles — the warn log line includes policy class, user id, and seller id.
  2. If access is genuinely needed, an owner must change the membership's role; there is no self-service escalation.
  3. Developers: gate nav items and buttons on the pundit policy or membership role so the option is never offered to roles that would be denied.

Example fix

<%# before: shown to every team member %>
<%= link_to "Team", settings_team_path %>

<%# after: only roles whose policy allows it see the link %>
<%= link_to "Team", settings_team_path if policy([:settings, :team]).show? %>
Defensive patterns

Strategy: validation

Validate before calling

<%# Scope settings navigation by the viewer's membership role %>
<% if policy([:settings, :team]).show? %>
  <%= link_to "Team", settings_team_path %>
<% end %>

Type guard

# Ruby: check the membership role before offering the action
membership = logged_in_user.find_user_membership_for_seller(current_seller)
can_manage_team = membership&.role.to_s.in?(%w[owner admin])

Try / catch

# Handled centrally by the concern (401 JSON or flash + dashboard redirect);
# the message names the user's humanized role so support can explain the denial immediately

Prevention

When it happens

Trigger: A non-owner team member (e.g. Marketing, Analyst) opens an owner-only page such as /settings/password; a role-scoped nav link points at a controller action their policy denies; an API call made with team-member credentials against an owner-only endpoint.

Common situations: New teammates exploring settings they cannot access; a role downgraded while cached UI still shows elevated links; frontend rendering actions based on login state rather than membership role.

Related errors


AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21). Data as JSON: /api/errors/d007b1daefdce87e. Report an issue: GitHub.

Appendix: source

Thrown at app/controllers/concerns/pundit_authorization.rb:53

    def settings_main_user_not_authorized
      # This allows keeping the Nav link to settings_main_path, and redirect to the profile page for those roles
      # that don't have access to it
      # All roles have at least read-only access to the profile page
      redirect_to profile_path
    end

    # It could happen for reasons like:
    # - a UI element allows the user to access a resource that is not authorized
    # - the user manually accessed a page for which is not authorized (i.e. /settings/password by non-owner)
    # These are not usual use cases of the app, so logging it to be notified there are bugs that need fixing.
    # Also, do not log and do not set a flash alert when the user is switching accounts, as this is a normal use case.
    #
    def default_user_not_authorized(exception)
      Rails.logger.warn(debug_message(exception)) unless params["account_switched"]

      message = build_error_message
      if request.format.json? || request.format.js?
        render json: { success: false, error: message }, status: :unauthorized
      else
        flash[:alert] = message unless params["account_switched"]
        redirect_to dashboard_url
      end
    end

    def build_error_message
      # Some policies (like CommentContextPolicy#index?) do not require the user to be authenticated
      return "You are not allowed to perform this action." if
        !user_signed_in? ||
        logged_in_user.role_owner_for?(current_seller)

      team_membership = logged_in_user.find_user_membership_for_seller!(current_seller)

      "Your current role as #{team_membership.role.humanize} cannot perform this action."
    rescue ActiveRecord::RecordNotFound
      # This should not happen, but if it does, we want to be notified so we can fix it
      ErrorNotifier.notify("Team: Could not find membership for user #{logged_in_user.id} and seller #{current_seller.id}")

View on GitHub (pinned to afeacbd394)