instructure/canvas-lms · error · Lti::PlatformNotificationService::InvalidNoticeHandler

Validation failed: Notice type unknown, must be one of

Error message

Validation failed: Notice type unknown, must be one of [#{Lti::Pns::NoticeTypes::ALL.join(", ")}]

What it means

validate_notice_type! checks the given notice_type against Lti::Pns::NoticeTypes::ALL before subscribing or unsubscribing, raising InvalidNoticeHandler with an explicit 'Notice type unknown' message. The model also validates this for subscribing, but this class-level check guarantees consistent errors for unsubscribe too.

Solutions

  1. Use a constant from Lti::Pns::NoticeTypes (e.g. NoticeTypes::HELLO_WORLD) instead of a raw string.
  2. Check the allowed list via Lti::Pns::NoticeTypes::ALL and match casing exactly.
  3. Update tool configuration/JSON to reference a currently supported notice type.
  4. If a new notice type is genuinely needed, add it to Lti::Pns::NoticeTypes::ALL and its builders.

Example fix

# before
subscribe_tool_for_notice(tool:, notice_type: 'HelloWorld')
# after
subscribe_tool_for_notice(tool:, notice_type: Lti::Pns::NoticeTypes::HELLO_WORLD)
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, "unknown notice_type" unless Lti::Pns::NoticeTypes::ALL.include?(notice_type)

Try / catch

begin
  Lti::PlatformNotificationService.unsubscribe_tool_for_notice(tool:, notice_type:)
rescue Lti::PlatformNotificationService::InvalidNoticeHandler => e
  render json: { error: e.message }, status: :bad_request
end

Prevention

When it happens

Trigger: Calling subscribe_tool_for_notice or unsubscribe_tool_for_notice with a notice_type string not present in Lti::Pns::NoticeTypes::ALL (typo, wrong casing, deprecated/renamed notice type).

Common situations: LTI tool configuration referencing an old or renamed notification type; typos like 'HelloWorld' vs 'hello_world'; clients hardcoding notice types instead of using the NoticeTypes constants.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at app/services/lti/platform_notification_service.rb:105

    def notify_tools(cet_id_or_ids:, builders:)
      notice_type = get_notice_type(builders:)
      Lti::NoticeHandler.active.where(notice_type:, context_external_tool_id: cet_id_or_ids).find_each do |notice_handler|
        send_notices(notice_handler:, builders:)
      end
    end

    def notify_asset_processor(asset_processor, *builders)
      notice_type = get_notice_type(builders:)
      Lti::NoticeHandler.active.where(notice_type:, context_external_tool_id: asset_processor.context_external_tool_id).find_each do |notice_handler|
        send_notices(notice_handler:, builders:)
      end
    end

    def validate_notice_type!(notice_type)
      # This is also validated in the model, but we want to validate for
      # unsubscribing and have a consistent error also for subscribing
      unless Lti::Pns::NoticeTypes::ALL.include?(notice_type)
        raise InvalidNoticeHandler, "Validation failed: Notice type unknown, must be one of [#{Lti::Pns::NoticeTypes::ALL.join(", ")}]"
      end
    end
    private_class_method :validate_notice_type!

    def send_notices(notice_handler:, builders:)
      builders.each_slice(notice_handler.max_batch_size || builders.length) do |batch|
        send_notice_batch(notice_handler:, builders: batch)
      end
    end
    private_class_method :send_notices

    def send_notice_batch(notice_handler:, builders:)
      tool = notice_handler.context_external_tool
      global_id = generate_notification_uuid
      notice_objects = builders.map { |builder| builder.build(tool) }
      webhook_body = { notices: notice_objects }.to_json

      log_info = builders.map { |builder| builder.info_log(tool) }

View on GitHub (pinned to 1c9f0bb801)