instructure/canvas-lms · error · EmbedNotFoundError
Embed not found for resource type: #
Error message
Embed not found for resource type: #{embed[:resource_type]}, id: #{embed[:id]}, src: #{embed[:src]} What it means
mark_embed_as_converted walks scan_progress.results[:resources] to decrement counts and drop the converted embed; if the resource/embed entry it expects is not present in the progress hash (the lookup branch fails), it raises EmbedNotFoundError with the type, id, and src. This is a bookkeeping failure during bulk conversion rather than initial validation.
Solutions
- Ensure only one conversion job runs per scan progress (idempotency guard / unique job lock)
- Re-run the scan then retry conversion with a fresh progress record
- Make mark_embed_as_converted tolerant: skip/no-op (with log) when the entry is already absent instead of raising
- Serialize scan and convert phases so a re-scan cannot reset results mid-conversion
Example fix
// before
raise EmbedNotFoundError, "Embed not found for resource type: ..."
// after
Rails.logger.warn("embed already removed from progress: #{embed[:resource_type]} #{embed[:id]}")
return # idempotent no-op on double conversion Defensive patterns
Strategy: retry
Validate before calling
# before bulk conversion, ensure no other job holds the progress progress = Progress.find(scan_id) raise 'conversion already in progress' if progress.locked? # or use a unique-job adapter
Try / catch
begin
perform_embed_list_conversion(...)
rescue YoutubeMigrationService::EmbedNotFoundError => e
Rails.logger.warn("progress entry vanished (double conversion?): #{e.message}")
end Prevention
- Guard bulk conversion with unique-job/locking so it can't double-run
- Don't trigger a re-scan while conversion is in flight
- Make mark_embed_as_converted idempotent for already-removed entries
When it happens
Trigger: perform_embed_list_conversion processing an embed whose entry was already removed by a prior conversion, results were reset mid-run by a concurrent re-scan, or the key/embed shape changed between scan and convert phases.
Common situations: Duplicate conversion jobs running concurrently on the same Progress row (double-decrement); re-scan kicked off while bulk convert is running; stale job retried after completion; results hash shape mismatch after code changes.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- cannot start new migration while another one is running
- Cannot validate existence for resource type: #
- Course not found
- Embed not found in scan for resource: #
- Invalid resource group key: #
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/9ca7d0adedad3175.
Report an issue: GitHub.
Appendix: source
Thrown at app/services/youtube_migration_service.rb:717
(embed[:content_id].to_s.presence || "") ==
(resource_embed[:content_id].to_s.presence || "")
end
if found_embed
was_already_converted = resource[:embeds][index][:converted] == true
unless was_already_converted
resource[:embeds][index][:converted] = true
resource[:embeds][index][:converted_at] = Time.now.utc
resource[:converted_count] = (resource[:converted_count] || 0) + 1
scan_progress.results[:total_converted] = (scan_progress.results[:total_converted] || 0) + 1
scan_progress.results[:total_count] = [scan_progress.results[:total_count] - 1, 0].max
end
scan_progress.results[:resources][key] = resource
scan_progress.save!
else
raise EmbedNotFoundError, "Embed not found for resource type: #{embed[:resource_type]}, id: #{embed[:id]}, src: #{embed[:src]}"
end
end
def process_new_quizzes_scan_update(scan_id, new_quizzes_scan_status:, new_quizzes_scan_results: {})
progress = self.class.find_scan(course, scan_id)
results = progress.results || {}
results[:new_quizzes_scan_status] = new_quizzes_scan_status
begin
if new_quizzes_scan_status == "completed"
scan_results = (new_quizzes_scan_results || {}).deep_symbolize_keys
new_quizzes_resources = {}
resources_array = scan_results[:resources] || []
resources_array.each do |resource|
key = YoutubeMigrationService.generate_resource_key(resource[:type], resource[:id])
new_quizzes_resources[key] = resource
endView on GitHub (pinned to 1c9f0bb801)