instructure/canvas-lms · error · OtherError

Invalid upload type

Error message

Invalid upload type

What it means

After validating the item type, do_import checks that uploadType is exactly "zipPackage". The Respondus SOAP import protocol only supports zipped IMS/QTI packages; any other upload format is rejected with OtherError.

Solutions

  1. Send uploadType as exactly "zipPackage" (case-sensitive)
  2. Zip the QTI/IMS package before uploading and confirm the client sends it as a zip package
  3. Check the Respondus client server-type profile is set to Canvas

Example fix

// before
client.publish("quiz", xmlData, "qtiPackage")
// after
client.publish("quiz", zipData, "zipPackage")
Defensive patterns

Strategy: validation

Validate before calling

if (uploadType !== "zipPackage") throw new Error("uploadType must be exactly 'zipPackage'");

Try / catch

begin
  servant.publishServerItem(session, itemType, uploadType, ...)
rescue RespondusApi::OtherError
  zip the package and resend
end

Prevention

When it happens

Trigger: Calling publishServerItem/replaceServerItem with uploadType set to anything other than "zipPackage" (e.g. "file", "qtiPackage", wrong casing like "ZipPackage").

Common situations: Client configured for a non-Canvas server type that allows other upload formats; hand-rolled SOAP clients passing raw XML or unzipped QTI; version mismatch between client and Canvas plugin expectations.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at gems/plugins/respondus_soap_endpoint/lib/respondus_soap_endpoint/urn_RespondusAPIServant.rb:550

    end

    ASSET_TYPES = {
      "quiz" => "Quizzes::Quiz",
      "qdb" => "AssessmentQuestionBank",
    }.freeze

    ATTACHMENT_FOLDER_NAME = "imported qti files"

    def do_import(item, itemType, uploadType, _fileName, fileData)
      if fileData == "\x0" && session["pending_migration_id"]
        return poll_for_completion
      end

      unless %w[quiz qdb].include?(itemType)
        raise OtherError, "Invalid item type"
      end
      if uploadType != "zipPackage"
        raise OtherError, "Invalid upload type"
      end

      selection_state = session["selection_state"] || []
      course = Course.where(id: selection_state.first).first
      raise(OtherError, "Item type incompatible with selection state") unless course

      # Make sure that the image import folder is hidden by default
      Folder.assert_path(ATTACHMENT_FOLDER_NAME, course) do |folder|
        folder.hidden = true
      end

      settings = {
        migration_type: "qti_converter",
        apply_respondus_settings_file: (itemType != "qdb"),
        skip_import_notification: true,
        files_import_allow_rename: true,
        files_import_root_path: ATTACHMENT_FOLDER_NAME,
        flavor: Qti::Flavors::RESPONDUS

View on GitHub (pinned to 1c9f0bb801)