instructure/canvas-lms · error · EmbedNotFoundError
Embed not found in scan for resource: #
Error message
Embed not found in scan for resource: #{resource_group_key} What it means
The resource exists in scan results but no scanned embed matches the given embed on all of src, field, and resource_type. EmbedNotFoundError is raised, meaning this particular embed (URL + RCE field + type combination) was not captured for that resource during the scan.
Solutions
- Re-run the scan after content edits so the embed snapshot is current
- Compare the embed's src/field/resource_type against scan.results[:resources][key][:embeds] entries
- Normalize the src (same format the scanner records, e.g. canonical YouTube URL) before calling convert_embed
- Ensure field is passed consistently (symbol vs string is handled by .to_s, but the name itself must match)
Example fix
// before
convert_embed(scan_id, { resource_type: 'WikiPage', id: id, src: edited_url, field: :body })
// after
scan = YoutubeMigrationService.find_scan(course, scan_id)
recorded = scan.dig(:results, :resources, "WikiPage|#{id}".to_sym, :embeds)
match = recorded&.find { |e| e[:src] == canonical_youtube_url(edited_url) }
raise 'embed not in latest scan; re-scan' unless match
convert_embed(scan_id, embed) Defensive patterns
Strategy: validation
Validate before calling
scan = YoutubeMigrationService.find_scan(course, scan_id)
key = "#{embed[:resource_type]}|#{embed[:id]}"
embeds = scan.results.dig(:resources, key.to_sym, :embeds) || []
raise 'embed not captured in scan' unless embeds.any? { |e| e[:src] == embed[:src] && e[:field].to_s == embed[:field].to_s } Try / catch
begin
service.convert_embed(scan_id, embed)
rescue YoutubeMigrationService::EmbedNotFoundError => e
Rails.logger.warn("#{e.message}; re-scanning")
YoutubeMigrationService.run_scan(course)
end Prevention
- Keep src in the same canonical form the scanner records
- Don't edit embed URLs/fields between scan and convert
- Diff current content embeds against the scan snapshot before converting
When it happens
Trigger: convert_embed called with an embed whose src URL differs from the scanned one (e.g. normalized/rewritten youtu.be vs youtube.com), whose field name differs in type/string form handling beyond .to_s, or which was edited after the scan.
Common situations: Video URL edited between scan and convert; embed moved to a different field; hand-crafted embed hash with mismatched casing or extra parameters in src; scan performed before an LTI/Studio rewrite changed src values.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Cannot validate existence for resource type: #
- Course not found
- Embed not found for resource type: #
- Invalid resource group key: #
- No migration file found
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/ebd9baeeb95e7059.
Report an issue: GitHub.
Appendix: source
Thrown at app/services/youtube_migration_service.rb:161
raise EmbedNotFoundError, "Scan not found for id: #{scan_id}"
end
def validate_embed_exists_in_scan!(scan_id, embed)
scan = YoutubeMigrationService.find_scan(course, scan_id)
resource_group_key = resource_group_key_for(embed)
return if scan.results.blank? || scan.results[:resources].blank?
resource = scan.results[:resources][resource_group_key]
raise EmbedNotFoundError, "Resource not found in scan for key: #{resource_group_key}" if resource.blank?
embed_exists = resource[:embeds].any? do |scan_embed|
scan_embed[:src] == embed[:src] &&
scan_embed[:field].to_s == embed[:field].to_s &&
scan_embed[:resource_type] == embed[:resource_type]
end
raise EmbedNotFoundError, "Embed not found in scan for resource: #{resource_group_key}" unless embed_exists
end
def prepare_new_quiz_resource_type(resource_type)
case resource_type
when /QuizzesNext::Quiz/
"QuizzesNext::Quiz"
when /QuizzesNext::Bank/
"QuizzesNext::Bank"
else
resource_type
end
end
def validate_supported_resource!(resource_type)
supported = SUPPORTED_RESOURCES.include?(resource_type) || NEW_QUIZZES_RESOURCES.include?(resource_type)
raise UnsupportedResourceTypeError, "Unsupported resource type: #{resource_type}" unless supported
end
View on GitHub (pinned to 1c9f0bb801)