CanCanCommunity/cancancan · error · CanCan::Error

You can't specify target (#{target}) as alias because it is

Error message

You can't specify target (#{target}) as alias because it is real action name

What it means

Ability#validate_target (lib/cancan/ability.rb:167) runs on every alias_action call. A new alias target must not collide with any action name that already appears as a source action in aliased_actions (the flattened values), because an alias expands to its component actions at rule-match time and a target that is itself a real action would make matching ambiguous. Default aliases (read => [index, show], etc.) already occupy the common RESTful names.

Source

Thrown at lib/cancan/ability.rb:167

    #
    #   can :read, :all
    #   cannot :read, Comment
    #
    # A block can be passed just like "can", however if the logic is complex it is recommended
    # to use the "can" method.
    #
    #   cannot :read, Product do |product|
    #     product.invisible?
    #   end
    #
    def cannot(action = nil, subject = nil, *attributes_and_conditions, &block)
      add_rule(Rule.new(false, action, subject, *attributes_and_conditions, &block))
    end

    # User shouldn't specify targets with names of real actions or it will cause Seg fault
    def validate_target(target)
      error_message = "You can't specify target (#{target}) as alias because it is real action name"
      raise Error, error_message if aliased_actions.values.flatten.include? target
    end

    def model_adapter(model_class, action)
      adapter_class = ModelAdapters::AbstractAdapter.adapter_class(model_class)
      adapter_class.new(model_class, relevant_rules_for_query(action, model_class))
    end

    # See ControllerAdditions#authorize! for documentation.
    def authorize!(action, subject, *args)
      message = args.last.is_a?(Hash) && args.last.key?(:message) ? args.pop[:message] : nil
      if cannot?(action, subject, *args)
        message ||= unauthorized_message(action, subject)
        raise AccessDenied.new(message, action, subject, args)
      end
      subject
    end

    def attributes_for(action, subject)

View on GitHub (pinned to 8c1bf153a3)

Solutions

  1. Pick a target name that is not an existing action or alias source (:see, :browse, :crud, :manage are safe vocabulary).
  2. If you want an 'alias of an alias', alias the same underlying actions directly to the new target instead of chaining.
  3. Inspect collisions first: puts ability.aliased_actions in a console to see every occupied name (keys and flattened values).

Example fix

# before
alias_action :index, :show, to: :read   # default
alias_action :read, to: :show           # CanCan::Error: target :show is a real action name

# after
alias_action :index, :show, to: :read   # default
alias_action :read, to: :see            # :see is not an existing action name
Defensive patterns

Strategy: validation

Validate before calling

target = :see
occupied = ability.aliased_actions.values.flatten.map(&:to_s)
raise ArgumentError, "#{target} collides with a real action" if occupied.include?(target.to_s)
ability.alias_action :index, :show, to: target

Try / catch

begin
  alias_action :read, to: :see
rescue CanCan::Error => e
  Rails.logger.error("alias collision: #{e.message}")
end

Prevention

When it happens

Trigger: alias_action :read, to: :show raises because :show is a real (default-aliased) action name; aliasing to a name already used as a source in another alias, e.g. alias_action :create, :read, to: :crud followed by alias_action :crud, to: :manage is fine, but alias_action :crud, to: :read-style reuse of occupied names is not; merging abilities whose alias vocabularies overlap this way.

Common situations: Teams inventing CRUD meta-actions (:crud, :see, :modify) and accidentally reusing RESTful verb names; copy-pasting alias_action lines between apps with different alias sets; upgrading when default aliases changed.

Related errors


AI-assisted analysis of CanCanCommunity/cancancan@8c1bf153a3 (2026-08-21). Data as JSON: /api/errors/df42233a2378e733. Report an issue: GitHub.