{"record":{"id":"00e2c680d9b569a3","repo":"instructure/canvas-lms","slug":"invalid-contribution-status-params-contribution-status-must","errorCode":null,"errorMessage":"Invalid contribution_status: #{params[:contribution_status]}. Must be one of: #{VALID_CONTRIBUTION_STATUSES.join(\", \")}","messagePattern":"Invalid contribution_status: #(.+?)\\. Must be one of: #(.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"app/models/lti/pns/lti_asset_processor_contribution_notice_builder.rb","lineNumber":65,"sourceCode":"        @params = params\n        ensure_lti_ids\n        super()\n      end\n\n      def validate_params!(params)\n        REQUIRED_PARAMS.each do |param_name|\n          raise ArgumentError, \"Missing required parameter: #{param_name}\" unless params[param_name]\n        end\n        params[:assets].each do |asset|\n          REQUIRED_ASSETS_PARAMS.each do |asset_param_name|\n            raise ArgumentError, \"Missing required asset parameter #{asset_param_name}\" unless asset[asset_param_name]\n          end\n        end\n        if params[:assets].any? && params[:asset_report_service_url].blank?\n          raise ArgumentError, \"Missing required parameter: asset_report_service_url when assets are present\"\n        end\n        unless VALID_CONTRIBUTION_STATUSES.include?(params[:contribution_status])\n          raise ArgumentError, \"Invalid contribution_status: #{params[:contribution_status]}. Must be one of: #{VALID_CONTRIBUTION_STATUSES.join(\", \")}\"\n        end\n      end\n\n      def notice_type\n        NoticeTypes::ASSET_PROCESSOR_CONTRIBUTION\n      end\n\n      def custom_ims_claims(_tool)\n        discussion_entry_version = @params[:discussion_entry_version]\n        discussion_entry = discussion_entry_version.discussion_entry\n        {\n          for_user: {\n            user_id: @params[:for_user_id],\n          },\n          assetreport: @params[:asset_report_service_url]&.then do |url|\n            {\n              scope: [\n                TokenScopes::LTI_ASSET_REPORT_SCOPE","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/lti/pns/lti_asset_processor_contribution_notice_builder.rb#L47-L83","documentation":"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.","triggerScenarios":"Passing a contribution_status string not in VALID_CONTRIBUTION_STATUSES (typo, wrong case, or new upstream value the builder doesn't know).","commonSituations":"Upstream asset processor service emitting a new status value; callers passing symbols instead of expected strings or vice versa; typos like 'complted'.","solutions":["Set contribution_status to one of the values listed in VALID_CONTRIBUTION_STATUSES","Normalize/map upstream status values to the accepted enum before building the notice","Rescue ArgumentError and log the invalid value for schema-drift follow-up"],"exampleFix":"// before\n{ contribution_status: \"DONE\" }\n// after\nVALID = Lti::Pns::LtiAssetProcessorContributionNoticeBuilder::VALID_CONTRIBUTION_STATUSES\nstatus = upstream_status.downcase\nraise \"unknown status\" unless VALID.include?(status)\nparams[:contribution_status] = status","handlingStrategy":"validation","validationCode":"valid = Lti::Pns::LtiAssetProcessorContributionNoticeBuilder::VALID_CONTRIBUTION_STATUSES\nraise \"bad status\" unless valid.include?(params[:contribution_status])","typeGuard":"def valid_status?(s) = Lti::Pns::LtiAssetProcessorContributionNoticeBuilder::VALID_CONTRIBUTION_STATUSES.include?(s)","tryCatchPattern":"begin\n  Builder.new(params)\nrescue ArgumentError => e\n  Rails.logger.error(\"PNS builder: #{e.message}\")\nend","preventionTips":["Map upstream statuses to the accepted enum","Keep VALID_CONTRIBUTION_STATUSES in sync with producers","Normalize case/type before passing status"],"tags":["lti","enum","params-validation"],"backgroundTag":"invalid-enum-value","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}