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
- Read REQUIRED_ASSETS_PARAMS and ensure every hash in params[:assets] contains all of those keys.
- Filter out incomplete assets before building: assets.select { |a| REQUIRED keys present } or reload the missing data.
- Log/inspect the offending asset to find which pipeline stage dropped the field.
- 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
- Validate each asset hash against REQUIRED_ASSETS_PARAMS before batching
- Reload assets from the DB at notice-build time instead of trusting serialized snapshots
- Log the offending asset when filtering out incomplete ones
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
- Missing required parameter: copied_at
- Missing required parameter: course
- Missing required parameter: #
- e.message
- Validation failed: Notice type unknown, must be one of
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)