instructure/canvas-lms · error · Canvas::Migration::Error

Error identifying package type

Error message

Error identifying package type: %{error}

What it means

Canvas::Migration::PackageIdentifier#identify_package rescues any exception raised while probing a content package (zip/QTI/etc.) and re-raises it as Canvas::Migration::Error with the original message interpolated. It means the migration tool could not even determine what kind of package the uploaded file is.

Solutions

  1. Ask the user to re-export/re-upload the package; verify it opens as a valid zip
  2. Check the interpolated error message ($!.message) for the underlying cause (e.g. Zip::Error vs ERB parse error)
  3. Validate the file (unzip -t) before submitting it to the importer
  4. Increase temp/disk availability on the app server if extraction failed from ENOSPC

Example fix

// before (caller, unguarded)
converter_class = Canvas::Migration::PackageIdentifier.identify_package(path)
// after
begin
  converter_class = Canvas::Migration::PackageIdentifier.identify_package(path)
rescue Canvas::Migration::Error => e
  flash[:error] = e.message
end
Defensive patterns

Strategy: try-catch

Validate before calling

raise 'not a zip' unless File.exist?(path) && File.open(path, 'rb') { |f| f.read(4) } == 'PK\x03\x04'

Type guard

def zip?(path)
  File.file?(path) && File.size(path) > 0 && File.open(path, 'rb') { |f| f.read(4) } == 'PK\x03\x04'
end

Try / catch

begin
  type = Canvas::Migration::PackageIdentifier.identify_package(path)
rescue Canvas::Migration::Error => e
  errors.add(:package, e.message)
end

Prevention

When it happens

Trigger: Calling Canvas::Migration::PackageIdentifier.identify_package on a corrupt archive, a non-zip file renamed to .zip/.imscc, an empty file, or a file unreadable by the archive library (Zip::Error, etc.).

Common situations: Users upload truncated exports, files uploaded mid-download, wrong file type uploaded in course copy/import UI, disk space issues corrupting temp extraction.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at lib/canvas/migration/package_identifier.rb:95

        elsif has_namespace(doc, "http://www.adlnet.org/xsd/adl_cp_rootv1p1")
          :scorm_1_1
        elsif has_namespace(doc, "http://www.adlnet.org/xsd/adlcp_rootv1p2")
          :scorm_1_2
        elsif has_namespace(doc, "http://www.adlnet.org/xsd/adlcp_v1p3")
          :scorm_1_3 # scorm 2004
        elsif doc.at_css("resources resource[type^=ims_qti]") ||
              doc.at_css("resources resource[type^=imsqti]")
          :qti
        else
          # generic IMS Content Package?
          :unknown_ims_cp_package
        end
      else
        :unknown
      end
    rescue
      # Not a valid archive file
      raise Canvas::Migration::Error,
            I18n.t(:package_error,
                   "Error identifying package type: %{error}",
                   error: $!.message),
            $!.backtrace
    end

    private

    # Common Cartridge 1.3 supports having just a single xml file
    # if it's not CC 1.3 then we don't know how to handle it
    def check_flat_xml_file
      doc = create_xml_doc(File.read(@archive.file))
      if get_node_val(doc, "metadata schema") =~ COMMON_CARTRIDGE_REGEX &&
         get_node_val(doc, "metadata schemaversion") == "1.3.0"
        :common_cartridge_1_3
      else
        :unknown
      end

View on GitHub (pinned to 1c9f0bb801)