instructure/canvas-lms · error

Error running python qti converter: #

Error message

Error running python qti converter: #{output}

What it means

The QTI module shells out to the python QTI converter and checks $?.exitstatus after conversion. A non-zero exit means the converter failed; the raw converter output is embedded in the raised message so operators can diagnose the underlying python-side failure.

Solutions

  1. Read the converter output in the error message for the actual python traceback / failure cause.
  2. Validate the source QTI package (unzip it, check imsmanifest.xml and XML well-formedness) and re-export from the source LMS if corrupt.
  3. Ensure the python converter's dependencies and correct python version are installed on the job host.
  4. Retry the migration; if a specific question type crashes the converter, remove or convert that item manually first.
  5. Check permissions/writability of the temp directories used for the conversion.

Example fix

// before
# converter crashes: missing lxml in python env
// after (on job host)
python3 -m pip install lxml   # converter dependency
# re-run the QTI import; exit status becomes 0
Defensive patterns

Strategy: try-catch

Validate before calling

# pre-flight: verify converter binary and deps
system('python3', '-c', 'import lxml') or raise 'qti converter python deps missing'

Try / catch

begin
  questions, assessments = Qti.migrate_tqi(src, dest, opts)
rescue RuntimeError => e
  raise unless e.message.start_with?('Error running python qti converter:')
  logger.error(e.message) # output contains the python traceback
  raise MigrationError, 'QTI conversion failed; see logs for converter output'
end

Prevention

When it happens

Trigger: Running canvas_migrate_qti (conversion in qti.rb) where the python converter subprocess exits non-zero — invalid/corrupt QTI package input, missing python dependencies for the converter, wrong python version, unreadable source files, or converter crash on a specific item type.

Common situations: Importing a QTI zip exported from another LMS with unsupported question types; converter's python dependencies not installed on a new host; QTI package with malformed XML; disk/permission issues in the temp conversion directories.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


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

Appendix: source

Thrown at gems/plugins/qti_exporter/lib/qti.rb:107

  def self.convert_xml(xml, opts = {})
    assessments = nil
    questions = nil
    Dir.mktmpdir do |dirname|
      xml_file = File.join(dirname, opts[:file_name] || "qti.xml")
      File.open(xml_file, "w") { |f| f << xml }

      # convert to 2.1
      dest_dir_2_1 = File.join(dirname, "qti_2_1")
      command = Qti.get_conversion_command(dest_dir_2_1, dirname)
      output = `#{command}`

      if $?.exitstatus == 0
        manifest = File.join(dest_dir_2_1, "imsmanifest.xml")
        questions = convert_questions(manifest, opts)
        assessments = convert_assessments(manifest, opts)
      else
        raise "Error running python qti converter: #{output}"
      end
    end
    [questions, assessments]
  end

  def self.convert_files(manifest_path)
    attachments = []
    doc = Nokogiri::XML(File.open(manifest_path))
    resource_nodes = doc.css("resource")
    doc.css("file").each do |file|
      # skip resource nodes, which are things like xml metadata and other sorts
      next if resource_nodes.any? { |node| node["href"] == file["href"] }

      # anything left is a file that needs to become an attachment on the context
      attachments << CGI.unescape(file["href"])
    end
    attachments
  end

View on GitHub (pinned to 1c9f0bb801)