{"record":{"id":"5aede742744c2dd0","repo":"instructure/canvas-lms","slug":"att-upload-error-message","errorCode":null,"errorMessage":"att.upload_error_message","messagePattern":"att\\.upload_error_message","errorType":"exception","errorClass":"Canvas::Migration::Error","httpStatus":null,"severity":"error","filePath":"lib/canvas/migration/worker.rb","lineNumber":95,"sourceCode":"\n  def self.clear_exported_data(folder)\n    config = ConfigFile.load(\"external_migration\")\n    if (!config || !config[:keep_after_complete]) && File.exist?(folder)\n      FileUtils.rm_rf(folder)\n    end\n  rescue\n    Rails.logger.warn \"Couldn't clear export data for content_migration #{content_migration.id}\"\n  end\n\n  def self.download_attachment(cm, url)\n    att = Attachment.new\n    att.context = cm\n    att.file_state = \"deleted\"\n    att.workflow_state = \"unattached\"\n    att.clone_url(url, false, true, quota_context: cm.context)\n\n    if att.file_state == \"errored\"\n      raise Canvas::Migration::Error, att.upload_error_message\n    end\n\n    cm.attachment = att\n    cm.save!\n    att\n  rescue Attachment::OverQuotaError\n    raise Canvas::Migration::Error, $!.message\n  end\nend\n","sourceCodeStart":77,"sourceCodeEnd":105,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/canvas/migration/worker.rb#L77-L105","documentation":"In Canvas::Migration::Worker#download_and_import_attachment (attachment cloning from a file_url), after att.clone_url the attachment is checked for file_state == 'errored'; if so, the attachment's upload_error_message is raised as Canvas::Migration::Error. It signals InstFS/S3 upload of the cloned URL failed.","triggerScenarios":"Canvas::Migration::Worker.download_attachment called with a file_url whose clone_url fails — unreachable or expired URL, quota exceeded flagging errored state, InstFS rejection.","commonSituations":"Course copy referencing external file URLs that expired, source attachments deleted, inst-fs/S3 outage during migration, oversized file exceeding quota.","solutions":["Check the rendered message (att.upload_error_message) for the concrete cause (quota, 404, etc.)","Verify the source file_url is still valid and publicly resolvable from the server/InstFS","Ensure the migration context has enough quota; the rescue below maps OverQuotaError separately","Retry the migration; transient storage failures mark the attachment errored"],"exampleFix":"// before (caller)\natt = Canvas::Migration::Worker.download_attachment(cm, url)\n// after\nbegin\n  att = Canvas::Migration::Worker.download_attachment(cm, url)\nrescue Canvas::Migration::Error => e\n  cm.fail_with_error!(e)\nend","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  att = Canvas::Migration::Worker.download_attachment(cm, url)\nrescue Canvas::Migration::Error => e\n  cm.fail_with_error!(e)\nend","preventionTips":["Validate source file URLs resolve (HEAD request) before migration","Ensure quota headroom on the target context","Monitor InstFS/S3 health during bulk imports"],"tags":["content-migration","attachment","instfs"],"backgroundTag":"http-request-failed","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"}