instructure/canvas-lms · error

Invalid consumer #

Error message

Invalid consumer #{consumer.class}

What it means

DiscussionTopic::ScopedToSections.for is a factory that only accepts a DiscussionTopicsController instance as the consumer. Any other controller or object passed in (e.g. another controller reusing ScopedToUser-style scoping) is rejected with this error, since the section-scoped filtering logic is written specifically for discussion topic views.

Solutions

  1. Only call .for from DiscussionTopicsController with self as the consumer
  2. If you need scoping elsewhere, build DiscussionTopic::ScopedToSections.new(context, user, relation) directly or extract shared logic
  3. Pass the controller instance, not the class or a different controller
  4. Use DiscussionTopic::ScopedToUser for non-controller contexts as the older classes do

Example fix

// before
discussions = DiscussionTopic::ScopedToSections.for(DiscussionTopicsController, @context, @current_user, scope)
// after
discussions = DiscussionTopic::ScopedToSections.for(self, @context, @current_user, scope) # inside DiscussionTopicsController
Defensive patterns

Strategy: type-guard

Validate before calling

raise 'wrong consumer' unless consumer.instance_of?(DiscussionTopicsController)
DiscussionTopic::ScopedToSections.for(consumer, context, user, relation)

Type guard

def discussion_topics_controller?(obj)
  obj.instance_of?(DiscussionTopicsController)
end

Try / catch

begin
  DiscussionTopic::ScopedToSections.for(self, context, user, relation)
rescue RuntimeError => e
  raise unless e.message.start_with?('Invalid consumer')
  relation # fall back to unscoped relation
end

Prevention

When it happens

Trigger: Calling DiscussionTopic::ScopedToSections.for(obj, context, user, relation) where obj.class is not DiscussionTopicsController — e.g. passing the controller class instead of an instance, self from a different controller, or nil.

Common situations: Refactoring a controller to reuse section scoping and passing the wrong object; calling .for from an API controller (DiscussionTopics::ApiController) that this class intentionally does not support; tests passing a double/stub that is not an instance.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/6281813e64eb3eeb. Report an issue: GitHub.

Appendix: source

Thrown at app/models/discussion_topic/scoped_to_sections.rb:30

# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.

class DiscussionTopic::ScopedToSections < ScopeFilter
  # tl;dr this pattern isn't intended to be re-used
  #
  # DiscussionTopic::ScopedToUser is currently used in tandem with this class. The
  # functionality of this class _should_ belong in there. However, because ScopedToUser
  # is used by multiple classes for multiple contexts, we are opting to separate the
  # logic to this one class. This allows for a fix for filtering visible discussions
  # prior to pagination, whereas previously we were paginating prior to filtering.
  # That allowed for some pages to end up blank. See https://instructure.atlassian.net/browse/KNO-372
  def self.for(consumer, context, user, relation)
    raise "Invalid consumer #{consumer.class}" unless consumer.instance_of?(DiscussionTopicsController)

    DiscussionTopic::ScopedToSections.new(context, user, relation)
  end

  def scope
    concat_scope do
      scope_for_user_sections(@relation)
    end
  end

  private

  def scope_for_user_sections(scope)
    return scope if context.grants_any_right?(
      user,
      :read_as_admin,
      :manage_grades,
      *RoleOverride::GRANULAR_MANAGE_ASSIGNMENT_PERMISSIONS,

View on GitHub (pinned to 1c9f0bb801)