instructure/canvas-lms · error · Lti::SubscriptionsValidator::MissingCapability

EventType # is invalid

Error message

EventType #{event_type} is invalid

What it means

Raised by Lti::SubscriptionsValidator#check_required_capabilities! when a requested LiveEvents subscription EventTypes entry is not a key in ToolConsumerProfile.webhook_subscription_capabilities — i.e. the event type is not a recognized/valid webhook subscription event. Canvas validates each subscription event type against the Tool Consumer Profile before creating it.

Solutions

  1. Correct the EventTypes entry to a valid event name from the ToolConsumerProfile webhook subscription capabilities
  2. Fetch the tool consumer profile to enumerate supported event types before subscribing
  3. Upgrade Canvas if the event exists only in a newer release
  4. Remove the unsupported event type from the subscription

Example fix

// before
{ subscription: { EventTypes: ['submission_created'] } }
// after
{ subscription: { EventTypes: ['submission_created'] } } # verify name against ToolConsumerProfile.webhook_subscription_capabilities keys
Defensive patterns

Strategy: validation

Validate before calling

valid_events = ToolConsumerProfile.webhook_subscription_capabilities.keys.map(&:to_s)
bad = event_types - valid_events
raise "invalid event types: #{bad.join(',')}" if bad.any?

Try / catch

begin
  validator.validate_subscription_request!
rescue Lti::SubscriptionsValidator::MissingCapability => e
  render json: { error: e.message, supported: ToolConsumerProfile.webhook_subscription_capabilities.keys }, status: :bad_request
end

Prevention

When it happens

Trigger: POSTing to the LTI 2.x subscription API (via validate_subscription_request!) with subscription[:EventTypes] containing an event type string that does not exist in the tool consumer profile's capabilities hash.

Common situations: Typos in event type names (wrong casing, singular vs plural); requesting events introduced in a newer Canvas version than the one deployed; tools copying stale event lists from old documentation.

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/cc945b7962e2e892. Report an issue: GitHub.

Appendix: source

Thrown at app/controllers/lti/subscriptions_validator.rb:51

    CONTEXT_WHITELIST = {
      "root_account" => Account,
      "assignment" => Assignment
    }.freeze

    attr_reader :subscription, :tool_proxy

    def initialize(subscription, tool_proxy)
      @subscription = subscription.with_indifferent_access
      @tool_proxy = tool_proxy
    end

    def check_required_capabilities!
      capabilities_hash = ToolConsumerProfile.webhook_subscription_capabilities
      return if tool_proxy.enabled_capabilities.include?(ToolConsumerProfile.webhook_grant_all_capability)

      subscription[:EventTypes].each do |event_type|
        raise MissingCapability, "EventType #{event_type} is invalid" unless capabilities_hash.key?(event_type.to_sym)
        unless tool_proxy.enabled_capabilities.intersect?(capabilities_hash[event_type.to_sym])
          raise MissingCapability, "Missing required capability"
        end
      end
    end

    def check_tool_context!
      requested_context = subscription_context
      requested_context = requested_context.course if requested_context.respond_to?(:course)
      raise ToolNotInContext, "Tool does not have access to requested context" unless tool_proxy.active_in_context?(requested_context)
    end

    def validate_subscription_request!
      check_required_capabilities!
      check_tool_context!
    end

    def self.validate_subscription_context!(subscription)

View on GitHub (pinned to 1c9f0bb801)