instructure/canvas-lms · error · ArgumentError

Missing required asset parameter #

Error message

Missing required asset parameter #{asset_param_name}

What it means

After validating top-level params, validate_params! iterates params[:assets] and checks each asset hash for every key in REQUIRED_ASSETS_PARAMS, raising ArgumentError naming the missing asset parameter. It ensures every asset in an LTI Asset Processor Submission PNS notice carries the fields needed to render the notification.

Solutions

  1. Read REQUIRED_ASSETS_PARAMS and ensure every hash in params[:assets] contains all of those keys.
  2. Filter out incomplete assets before building: assets.select { |a| REQUIRED keys present } or reload the missing data.
  3. Log/inspect the offending asset to find which pipeline stage dropped the field.
  4. Add a caller-side validation that mirrors the builder's checks to fail earlier with better context.

Example fix

// before
Lti::Pns::LtiAssetProcessorSubmissionNoticeBuilder.new(course:, assets: submissions.map { |s| { asset_id: s.id } })
// after
assets = submissions.map { |s| { asset_id: s.id, title: s.title } }
Lti::Pns::LtiAssetProcessorSubmissionNoticeBuilder.new(course:, assets:)
Defensive patterns

Strategy: validation

Validate before calling

req = Lti::Pns::LtiAssetProcessorSubmissionNoticeBuilder::REQUIRED_ASSETS_PARAMS
bad = params[:assets].reject { |a| req.all? { |k| a[k].present? } }
raise ArgumentError, "incomplete assets: #{bad.inspect}" if bad.any?

Try / catch

begin
  builder = Lti::Pns::LtiAssetProcessorSubmissionNoticeBuilder.new(params)
rescue ArgumentError => e
  Canvas::Errors.capture_exception(:lti_pns, e, :warn)
end

Prevention

When it happens

Trigger: Constructing the builder where one or more hashes inside params[:assets] lack a key from REQUIRED_ASSETS_PARAMS (e.g. an asset missing :asset_id or :title), typically when asset records were partially loaded or serialized incompletely.

Common situations: Batch submission events where some assets were deleted between event capture and notice build; serialization code that only includes asset attributes conditionally; hand-built test payloads missing per-asset fields.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at app/models/lti/pns/lti_asset_processor_submission_notice_builder.rb:48

        for_user_id
        notice_event_timestamp
        submission_lti_id
      ].freeze
      REQUIRED_ASSETS_PARAMS = %i[asset_id url sha256_checksum timestamp size content_type].freeze

      def initialize(params)
        validate_params!(params)
        @params = params
        super()
      end

      def validate_params!(params)
        REQUIRED_PARAMS.each do |param_name|
          raise ArgumentError, "Missing required parameter: #{param_name}" unless params[param_name]
        end
        params[:assets].each do |asset|
          REQUIRED_ASSETS_PARAMS.each do |asset_param_name|
            raise ArgumentError, "Missing required asset parameter #{asset_param_name}" unless asset[asset_param_name]
          end
        end
      end

      def notice_type
        Lti::Pns::NoticeTypes::ASSET_PROCESSOR_SUBMISSION
      end

      def custom_ims_claims(_tool)
        {
          for_user: {
            user_id: @params[:for_user_id],
          },
          assetreport: {
            scope: [
              TokenScopes::LTI_ASSET_REPORT_SCOPE
            ],
            report_url: @params[:asset_report_service_url]

View on GitHub (pinned to 1c9f0bb801)