CanCanCommunity/cancancan · error · CanCan::NotImplemented

This model adapter does not support matching on a nested sub

Error message

This model adapter does not support matching on a nested subject.

What it means

AbstractAdapter#nested_subject_matches_conditions? (lib/cancan/model_adapters/abstract_adapter.rb:52) raises CanCan::NotImplemented. It is reached only when an adapter declares override_nested_subject_conditions_matching? true without implementing the method, i.e., an incomplete custom adapter handling nested subjects. Nested subject means rules whose conditions hash nests another model's conditions, such as can :read, Comment, project: { owner_id: 1 }.

Source

Thrown at lib/cancan/model_adapters/abstract_adapter.rb:52

      def self.matches_conditions_hash?(_subject, _conditions)
        raise NotImplemented, 'This model adapter does not support matching on a conditions hash.'
      end

      # Override if parent condition could be under a different key in conditions
      def self.parent_condition_name(parent, _child)
        parent.class.name.downcase.to_sym
      end

      # Used above override_conditions_hash_matching to determine if this model adapter will override the
      # matching behavior for nested subject.
      # If this returns true then nested_subject_matches_conditions? will be called.
      def self.override_nested_subject_conditions_matching?(_parent, _child, _all_conditions)
        false
      end

      # Override if override_nested_subject_conditions_matching? returns true
      def self.nested_subject_matches_conditions?(_parent, _child, _all_conditions)
        raise NotImplemented, 'This model adapter does not support matching on a nested subject.'
      end

      # Used to determine if this model adapter will override the matching behavior for a specific condition.
      # If this returns true then matches_condition? will be called. See Rule#matches_conditions_hash
      def self.override_condition_matching?(_subject, _name, _value)
        false
      end

      # Override if override_condition_matching? returns true
      def self.matches_condition?(_subject, _name, _value)
        raise NotImplemented, 'This model adapter does not support matching on a specific condition.'
      end

      def initialize(model_class, rules)
        @model_class = model_class
        @rules = rules
      end

View on GitHub (pinned to 8c1bf153a3)

Solutions

  1. Implement self.nested_subject_matches_conditions?(parent, child, all_conditions) in the adapter.
  2. Or return false from override_nested_subject_conditions_matching? to use the default matching path.
  3. As a user of a broken third-party adapter: flatten nested conditions (put the foreign key directly on the model: can :read, Comment, owner_id: user.id) to avoid the nested-subject code path.
  4. Update or patch the adapter gem to the version matching your cancancan release.

Example fix

# before (ability with nested conditions + incomplete adapter)
can :read, Comment, project: { owner_id: user.id }
# can?(:read, @comment) -> CanCan::NotImplemented on adapters claiming the override

# after (flatten the condition onto the model itself)
can :read, Comment, project_id: Project.where(owner_id: user.id).pluck(:id)
# or simply:
can :read, Comment, owner_id: user.id   # if the association lives on Comment
Defensive patterns

Strategy: validation

Validate before calling

# avoid nested-subject conditions when the adapter cannot handle them
can :read, Comment, owner_id: user.id         # flat: skips nested-subject matching
can :read, Comment, project_id: user.project_ids # flat FK instead of nested hash

Type guard

def adapter_supports_nested?(adapter, parent, child)
  !adapter.override_nested_subject_conditions_matching?(parent, child, {}) || adapter.method(:nested_subject_matches_conditions?).owner != CanCan::ModelAdapters::AbstractAdapter
end

Try / catch

begin
  can?(:read, @comment)
rescue CanCan::NotImplemented => e
  Rails.logger.error("adapter incomplete: #{e.message}")
  false
end

Prevention

When it happens

Trigger: A custom adapter returning true from override_nested_subject_conditions_matching?(parent, child, conditions) but not implementing nested_subject_matches_conditions?; then a nested-conditions rule like can :read, Comment, project: { owner_id: user.id } is instance-checked with can?(:read, @comment).

Common situations: Porting the ActiveRecord adapter to another ORM and missing the nested-subject branch; upgrading cancancan versions where the nested-subject contract changed and the vendored adapter was not updated.

Related errors


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