instructure/canvas-lms · error · ResourceNotFoundError

Resource not found for type: #

Error message

Resource not found for type: #{resource_type}, id: #{resource_id}

What it means

validate_resource_exists! looks up the actual record (e.g. WikiPage, Quizzes::Quiz, QuizQuestion, AssessmentQuestion, DiscussionTopic, Assignment, etc.) with .find. ActiveRecord::RecordNotFound is rescued and re-raised as ResourceNotFoundError naming the type and id, so conversion stops when the backing content no longer exists.

Solutions

  1. Verify the record still exists for that id in the same shard/course before converting; re-run the scan to refresh ids if content was recreated
  2. Skip this embed and continue converting the rest, logging the dangling reference
  3. If content was deleted intentionally, remove the embed from the content rather than converting
  4. Check that the resource_type matches the id's actual model (QuizQuestion id vs AssessmentQuestion id mix-ups)

Example fix

// before
service.convert_embed(scan_id, { resource_type: 'Quizzes::Quiz', id: deleted_quiz_id, ... })
// after
begin
  service.convert_embed(scan_id, embed)
rescue YoutubeMigrationService::ResourceNotFoundError => e
  Rails.logger.warn("skipping unconvertible embed: #{e.message}")
end
Defensive patterns

Strategy: try-catch

Validate before calling

model = embed[:resource_type].safe_constantize
raise 'record missing' unless model && embed[:resource_type] != 'CourseSyllabus' && model.where(id: embed[:id]).exists?

Try / catch

begin
  service.convert_embed(scan_id, embed)
rescue YoutubeMigrationService::ResourceNotFoundError => e
  Rails.logger.warn("dangling embed skipped: #{e.message}")
  next # continue with remaining embeds
end

Prevention

When it happens

Trigger: convert_embed where resource_id references a deleted record, an id from another course/shard, or a type whose id semantics differ (e.g. passing a quiz question's assessment_question id).

Common situations: Content deleted between scan and convert (weeks can pass); restoring/importing courses that reassign ids; migrating data across environments; soft-deleted or unpublished records the scan once saw.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at app/services/youtube_migration_service.rb:215

      course.discussion_topics.find(resource_id)
    when "DiscussionEntry"
      DiscussionEntry.find(resource_id)
    when "CalendarEvent"
      course.calendar_events.find(resource_id)
    when "Quizzes::Quiz"
      course.quizzes.find(resource_id)
    when "Quizzes::QuizQuestion"
      Quizzes::QuizQuestion.find(resource_id)
    when "AssessmentQuestion"
      AssessmentQuestion.find(resource_id)
    when "CourseSyllabus", "Course"
      # For syllabus, the resource_id is the course id
      raise ResourceNotFoundError, "Course not found" unless course.id == resource_id
    else
      raise ResourceNotFoundError, "Cannot validate existence for resource type: #{resource_type}"
    end
  rescue ActiveRecord::RecordNotFound
    raise ResourceNotFoundError, "Resource not found for type: #{resource_type}, id: #{resource_id}"
  end

  def convert_embed(scan_id, embed, user_uuid: nil)
    validate_scan_exists!(scan_id)
    validate_supported_resource!(embed[:resource_type])

    resource_group_key = embed[:resource_group_key] || YoutubeMigrationService.generate_resource_key(embed[:resource_type], embed[:id])
    validate_resource_group_key!(resource_group_key)
    validate_embed_exists_in_scan!(scan_id, embed)
    validate_resource_exists!(embed[:resource_type], embed[:id])

    message = YoutubeMigrationService.generate_resource_key(embed[:resource_type], embed[:id])
    # TODO: Something will listen on this creation
    convert_progress = Progress.create!(tag: CONVERT_TAG, context: course, message:, results: { original_embed: embed })

    job_priority = Account.site_admin.feature_enabled?(:youtube_migration_high_priority) ? Delayed::HIGH_PRIORITY : Delayed::LOW_PRIORITY
    n_strand = "youtube_embed_convert_#{course.global_id}_#{resource_group_key}"
    convert_progress.process_job(YoutubeMigrationService, :perform_conversion, { n_strand:, priority: job_priority }, course.id, scan_id, embed, user_uuid:)

View on GitHub (pinned to 1c9f0bb801)