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
- Pick a target name that is not an existing action or alias source (:see, :browse, :crud, :manage are safe vocabulary).
- If you want an 'alias of an alias', alias the same underlying actions directly to the new target instead of chaining.
- 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
- Keep a fixed alias vocabulary (:see, :crud, :manage, :browse) documented in the Ability class.
- Never chain alias_action targets; alias underlying actions directly.
- Print ability.aliased_actions in a console session before adding new aliases.
- Unit-test the Ability's alias table so accidental collisions fail in CI, not in production boots.
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
- Subject is required for #{action}
- A hash of conditions is mutually exclusive with a block. Che
- You are not authorized to access this page.
- The can? and cannot? call cannot be used with a raw sql 'can
- accessible_by_strategy = :subquery requires ActiveRecord 5 o
AI-assisted analysis of CanCanCommunity/cancancan@8c1bf153a3 (2026-08-21).
Data as JSON: /api/errors/df42233a2378e733.
Report an issue: GitHub.