{"record":{"id":"b22960a9395497b3","repo":"instructure/canvas-lms","slug":"description-additional-info","errorCode":null,"errorMessage":"#{description}: #{additional_info}","messagePattern":"#\\{description\\}: #\\{additional_info\\}","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"app/models/outcomes_service/migration_service.rb","lineNumber":156,"sourceCode":"            true\n          when \"failed\"\n            failure_desc = \"Content Import for Outcomes Service failed\"\n            add_failed_import_warning(import_data, failure_desc, json.to_s)\n          else\n            false\n          end\n        else\n          failure_desc = \"Error retrieving import state for Outcomes Service: #{response.body}\"\n          add_failed_import_warning(import_data, failure_desc)\n        end\n      end\n\n      private\n\n      def add_failed_import_warning(data, description, additional_info = \"\")\n        data[:content_migration].add_warning(I18n.t(\"%{desc}\", desc: description)) if data.key?(:content_migration)\n        if additional_info.present?\n          raise \"#{description}: #{additional_info}\"\n        else\n          raise description\n        end\n      end\n\n      def lookup_artifact(artifact_type, artifact_id, course)\n        case artifact_type\n        when \"canvas.page\"\n          course.wiki_pages.where(id: artifact_id).first\n        end\n      end\n\n      def headers_for(course, scope, overrides = {})\n        {\n          \"Authorization\" => OutcomesService::Service.jwt(course, scope, overrides:)\n        }\n      end\n","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/outcomes_service/migration_service.rb#L138-L174","documentation":"Raised by OutcomesService::MigrationService#add_failed_import_warning when checking import status (import_completed?) determines the Outcomes Service import failed, after attaching a warning to the associated ContentMigration. The message combines a failure description with extra info (typically the error response body or status). It aborts the migration-check flow with the failure detail.","triggerScenarios":"import_completed? receives a non-2xx response when GETting the content_import status URL, or the import JSON reports a failed/errored workflow_state, or the import_id cannot be resolved — then add_failed_import_warning is invoked with the description and additional_info.","commonSituations":"Outcomes Service import job failed server-side (bad content payload); import_id expired or belongs to a different service instance; transient 5xx while polling status; content_migration association missing so the warning path throws instead of only warning.","solutions":["Read description/additional_info in the error for the underlying Outcomes Service failure","Check the Outcomes Service logs for the import_id to see why the import failed","Verify the content_imports status URL and that the service instance is healthy","Re-run the outcome migration after fixing the payload or service-side error","Ensure data[:content_migration] is set so the failure is recorded as a warning on the migration"],"exampleFix":"// before\nraise \"#{description}: #{additional_info}\"\n// after\nif data.key?(:content_migration)\n  data[:content_migration].add_warning(I18n.t(\"%{desc} %{info}\", desc: description, info: additional_info))\n  data[:content_migration].fail!\nelse\n  raise \"#{description}: #{additional_info}\"\nend","handlingStrategy":"try-catch","validationCode":"import_data = { import_id:, course:, content_migration: }\nreturn unless import_data.key?(:content_migration) && import_data[:content_migration].present?","typeGuard":"valid = data.is_a?(Hash) && data.key?(:content_migration) && data[:import_id].present?","tryCatchPattern":"begin\n  done = service.import_completed?(import_data)\nrescue RuntimeError => e\n  import_data[:content_migration]&.add_warning(e.message)\n  import_data[:content_migration]&.fail!\nend","preventionTips":["Poll import status with exponential backoff to tolerate transient 5xx","Verify import_id belongs to the correct Outcomes Service instance","Always attach content_migration to import_data so failures become warnings, not raises","Check Outcomes Service job logs for failed imports before re-running migrations"],"tags":["http","outcomes-service","content-migration"],"backgroundTag":"upstream-api-error","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"}