instructure/canvas-lms · error · ArgumentError

Invalid contribution_status: #

Error message

Invalid contribution_status: #{params[:contribution_status]}. Must be one of: #{VALID_CONTRIBUTION_STATUSES.join(", ")}

What it means

Guard in Lti::Pns::LtiAssetProcessorContributionNoticeBuilder#validate_params!: params[:contribution_status] is not one of the allowed values (SUBMITTED, DELETED, HIDDEN), so ArgumentError is raised while building the LTI asset processor contribution notice.

Solutions

  1. Set contribution_status to one of the values listed in VALID_CONTRIBUTION_STATUSES
  2. Normalize/map upstream status values to the accepted enum before building the notice
  3. Rescue ArgumentError and log the invalid value for schema-drift follow-up

Example fix

// before
{ contribution_status: "DONE" }
// after
VALID = Lti::Pns::LtiAssetProcessorContributionNoticeBuilder::VALID_CONTRIBUTION_STATUSES
status = upstream_status.downcase
raise "unknown status" unless VALID.include?(status)
params[:contribution_status] = status
Defensive patterns

Strategy: validation

Validate before calling

valid = Lti::Pns::LtiAssetProcessorContributionNoticeBuilder::VALID_CONTRIBUTION_STATUSES
raise "bad status" unless valid.include?(params[:contribution_status])

Type guard

def valid_status?(s) = Lti::Pns::LtiAssetProcessorContributionNoticeBuilder::VALID_CONTRIBUTION_STATUSES.include?(s)

Try / catch

begin
  Builder.new(params)
rescue ArgumentError => e
  Rails.logger.error("PNS builder: #{e.message}")
end

Prevention

When it happens

Trigger: Passing a contribution_status string not in VALID_CONTRIBUTION_STATUSES (typo, wrong case, or new upstream value the builder doesn't know).

Common situations: Upstream asset processor service emitting a new status value; callers passing symbols instead of expected strings or vice versa; typos like 'complted'.

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

Appendix: source

Thrown at app/models/lti/pns/lti_asset_processor_contribution_notice_builder.rb:65

        @params = params
        ensure_lti_ids
        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
        if params[:assets].any? && params[:asset_report_service_url].blank?
          raise ArgumentError, "Missing required parameter: asset_report_service_url when assets are present"
        end
        unless VALID_CONTRIBUTION_STATUSES.include?(params[:contribution_status])
          raise ArgumentError, "Invalid contribution_status: #{params[:contribution_status]}. Must be one of: #{VALID_CONTRIBUTION_STATUSES.join(", ")}"
        end
      end

      def notice_type
        NoticeTypes::ASSET_PROCESSOR_CONTRIBUTION
      end

      def custom_ims_claims(_tool)
        discussion_entry_version = @params[:discussion_entry_version]
        discussion_entry = discussion_entry_version.discussion_entry
        {
          for_user: {
            user_id: @params[:for_user_id],
          },
          assetreport: @params[:asset_report_service_url]&.then do |url|
            {
              scope: [
                TokenScopes::LTI_ASSET_REPORT_SCOPE

View on GitHub (pinned to 1c9f0bb801)