instructure/canvas-lms · error · ArgumentError
Broadcast Policy block not supplied for #
Error message
Broadcast Policy block not supplied for #{self.class} What it means
broadcast_notifications runs as an after_save hook (and can be called manually) to broadcast an object's Broadcast Policy notifications. It requires the class to have registered policies via broadcast_policy { ... }; if broadcast_policy_list is nil, no policy block was ever declared for that class, and it raises ArgumentError naming the class.
Solutions
- Add a broadcast_policy block to the model: broadcast_policy { policy(:name) { ... } }
- Check that the module/concern defining broadcast_policy is actually included and loaded
- Remove or guard the manual broadcast_notifications call for models without policies
- Ensure broadcast_policy_list is defined on self.class (not just the singleton/parent) after refactors
Example fix
// before
class Announcement < ActiveRecord::Base; include BroadcastPolicy::InstanceMethods; end
// after
class Announcement < ActiveRecord::Base
include BroadcastPolicy::InstanceMethods
broadcast_policy do
policy(:create) { ... }
end
end Defensive patterns
Strategy: try-catch
Validate before calling
def has_broadcast_policies?(klass) klass.respond_to?(:broadcast_policy_list) && klass.broadcast_policy_list.present? end
Try / catch
begin
record.broadcast_notifications(prior_version)
rescue ArgumentError => e
Rails.logger.warn("skipping broadcast: #{e.message}")
end Prevention
- Declare a broadcast_policy block in every model that includes the concern
- Centralize policy definitions in a shared concern
- Test that save-time notifications don't raise for policy-less models
When it happens
Trigger: Calling instance.broadcast_notifications (or triggering save on a model that includes BroadcastPolicy::InstanceMethods) where the class never declared a broadcast_policy block — or declared it in a concern/parent class that isn't loaded.
Common situations: Invoking the callback manually in a console or job on a model without policies; moving broadcast_policy declarations during a refactor so the including class lost them; mixing up the BroadcastPolicy gem's DSL with Canvas's older notification callbacks.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- A new_id, '# ', referenced an existing # and the # with #…
- A new_integration_id, '#
- A student referenced a non-existent user #
- A user did not pass validation
- [A11Y Scan] Skipped resource #
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/7296f513dcbcb7da.
Report an issue: GitHub.
Appendix: source
Thrown at gems/broadcast_policy/lib/broadcast_policy/instance_methods.rb:86
end
@mutations_before_last_save = ActiveModel::AttributeMutationTracker.new(other_attributes)
previously_new_record = @previously_new_record
@previously_new_record = !new_record? && other.new_record?
end
yield
ensure
@changed_attributes = frd_changed_attributes
@mutations_before_last_save = frd_mutations_before_last_save
@previously_new_record = previously_new_record
end
end
# This is called after_save, but you can call it manually to trigger
# notifications. If you pass in a prior_version of self, its
# attributes will be used to fake out the various _was/_changed?
# helpers
def broadcast_notifications(prior_version = nil)
raise ArgumentError, "Broadcast Policy block not supplied for #{self.class}" unless self.class.broadcast_policy_list
if prior_version
with_changed_attributes_from(prior_version) do
self.class.broadcast_policy_list.broadcast(self)
end
else
self.class.broadcast_policy_list.broadcast(self)
end
end
attr_accessor :skip_broadcasts
def save_without_broadcasting
@skip_broadcasts = true
save
ensure
@skip_broadcasts = false
endView on GitHub (pinned to 1c9f0bb801)