instructure/canvas-lms · error · RuntimeError

# : #

Error message

#{description}: #{additional_info}

What it means

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.

Solutions

  1. Read description/additional_info in the error for the underlying Outcomes Service failure
  2. Check the Outcomes Service logs for the import_id to see why the import failed
  3. Verify the content_imports status URL and that the service instance is healthy
  4. Re-run the outcome migration after fixing the payload or service-side error
  5. Ensure data[:content_migration] is set so the failure is recorded as a warning on the migration

Example fix

// before
raise "#{description}: #{additional_info}"
// after
if data.key?(:content_migration)
  data[:content_migration].add_warning(I18n.t("%{desc} %{info}", desc: description, info: additional_info))
  data[:content_migration].fail!
else
  raise "#{description}: #{additional_info}"
end
Defensive patterns

Strategy: try-catch

Validate before calling

import_data = { import_id:, course:, content_migration: }
return unless import_data.key?(:content_migration) && import_data[:content_migration].present?

Type guard

valid = data.is_a?(Hash) && data.key?(:content_migration) && data[:import_id].present?

Try / catch

begin
  done = service.import_completed?(import_data)
rescue RuntimeError => e
  import_data[:content_migration]&.add_warning(e.message)
  import_data[:content_migration]&.fail!
end

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

Thrown at app/models/outcomes_service/migration_service.rb:156

            true
          when "failed"
            failure_desc = "Content Import for Outcomes Service failed"
            add_failed_import_warning(import_data, failure_desc, json.to_s)
          else
            false
          end
        else
          failure_desc = "Error retrieving import state for Outcomes Service: #{response.body}"
          add_failed_import_warning(import_data, failure_desc)
        end
      end

      private

      def add_failed_import_warning(data, description, additional_info = "")
        data[:content_migration].add_warning(I18n.t("%{desc}", desc: description)) if data.key?(:content_migration)
        if additional_info.present?
          raise "#{description}: #{additional_info}"
        else
          raise description
        end
      end

      def lookup_artifact(artifact_type, artifact_id, course)
        case artifact_type
        when "canvas.page"
          course.wiki_pages.where(id: artifact_id).first
        end
      end

      def headers_for(course, scope, overrides = {})
        {
          "Authorization" => OutcomesService::Service.jwt(course, scope, overrides:)
        }
      end

View on GitHub (pinned to 1c9f0bb801)