instructure/canvas-lms · error
Couldn't find QTI Migration Tool. See…
Error message
Couldn't find QTI Migration Tool. See https://github.com/instructure/QTIMigrationTool/wiki for installation instructions.
What it means
The qti_exporter plugin shells out to an external Python QTI Migration Tool binary to convert QTI packages. get_conversion_command raises this when the class variable @migration_executable was never located/initialized. It is a hard dependency failure: exports/conversions cannot proceed without the tool.
Solutions
- Install the QTI Migration Tool per https://github.com/instructure/QTIMigrationTool/wiki and make it executable
- Ensure the tool's directory is on PATH so the gem's executable lookup succeeds
- Verify in a console that QTI.migration_executable is set after boot
- For CI/dev-only environments that never export QTI, guard the export feature behind a feature flag or skip those specs
Example fix
// before (tool missing) $ which migration_tool # -> not found // after $ git clone https://github.com/instructure/QTIMigrationTool.git && export PATH=$PATH:/path/to/QTIMigrationTool
Defensive patterns
Strategy: validation
Validate before calling
raise 'QTI tool not installed' unless defined?(QTI) && QTI.migration_executable.present?
Try / catch
begin
QTI.get_conversion_command(out_dir, manifest)
rescue RuntimeError => e
raise unless e.message.include?('QTI Migration Tool')
Rails.logger.error('Install QTIMigrationTool: see wiki')
raise ExportSetupError
end Prevention
- Install the tool in every dev image and Dockerfile
- Add a boot-time or spec-level check that QTI.migration_executable is set
- Document PATH setup in onboarding docs
When it happens
Trigger: Calling QTI.get_conversion_command (or any export flow that reaches it, e.g. course copy/QTI export) when QTI.migration_executable was never set — the tool isn't installed, isn't on PATH, or the lookup in the gem's init failed to find it.
Common situations: Fresh dev environments or Docker images without the QTIMigrationTool cloned/built; the tool not added to PATH; upgrading Canvas and skipping the setup doc at the wiki link in the message.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- No question type used when trying to parse a qti question
- A new_id, '# ', referenced an existing # and the # with #…
- A new_integration_id, '#
- A student referenced a non-existent user #
- A user did not pass validation
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/a6527e59270f6670.
Report an issue: GitHub.
Appendix: source
Thrown at gems/plugins/qti_exporter/lib/qti.rb:129
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
def self.get_conversion_command(out_dir, manifest_file, file_path_prepend = nil)
if @migration_executable.nil?
raise "Couldn't find QTI Migration Tool. See https://github.com/instructure/QTIMigrationTool/wiki for installation instructions."
else
prepend = file_path_prepend ? "--pathprepend=\"#{file_path_prepend}\" " : ""
"\"#{@migration_executable}\" #{prepend}--ucvars --nogui --overwrite --cpout=#{Shellwords.escape(out_dir)} #{Shellwords.escape(manifest_file)} 2>&1"
end
end
end
View on GitHub (pinned to 1c9f0bb801)