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
- Only call .for from DiscussionTopicsController with self as the consumer
- If you need scoping elsewhere, build DiscussionTopic::ScopedToSections.new(context, user, relation) directly or extract shared logic
- Pass the controller instance, not the class or a different controller
- 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
- Call .for only with self from DiscussionTopicsController
- Use ScopedToSections.new directly when no controller is involved
- Don't pass controller classes or doubles
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
- Only a hash value is accepted for backup_submission_data…
- assessor and assessee required
- association required
- can only forward one conversation at a time
- can't accept
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)