instructure/canvas-lms · error · CCImportError
Invalid xml syntax
Error message
Invalid xml syntax
What it means
After namespace validation, convert_blti_xml runs XPath queries via convert_blti_link. A Nokogiri::XML::XPath::SyntaxError rescued there is re-raised as CCImportError 'Invalid xml syntax', meaning the document could not be evaluated with the expected XPath expressions — typically malformed or structurally unexpected XML.
Solutions
- Validate the XML with a parser (xmllint --noout config.xml) and fix syntax errors such as unescaped & or unclosed tags
- Log/inspect response.body before conversion to see exactly what the server returned
- Re-download the configuration XML from the tool provider
Example fix
# before (invalid) <launch_url>https://tool.example.com/launch?a=1&b=2</launch_url> # after (valid) <launch_url>https://tool.example.com/launch?a=1&b=2</launch_url>
Defensive patterns
Strategy: validation
Validate before calling
Nokogiri::XML(xml) { |c| c.strict }.parse # raises SyntaxError before import if malformed Type guard
def well_formed_xml?(xml)
Nokogiri::XML(xml) { |c| c.strict }
true
rescue Nokogiri::XML::SyntaxError
false
end Try / catch
begin
tool = converter.convert_blti_xml(xml)
rescue CCImportError => e
if e.message.include?('Invalid xml syntax')
Rails.logger.error("Malformed BLTI XML: #{xml.first(200)}")
end
raise
end Prevention
- Validate fetched XML with xmllint or strict Nokogiri parsing before import
- Escape special characters (&, <) when generating config XML
- Log response bodies on failure to spot HTML error pages served as XML
When it happens
Trigger: convert_blti_xml is given XML that parses loosely but breaks the XPath evaluation inside convert_blti_link — e.g. truncated documents, unescaped characters, or content served with a non-XML doctype/structure.
Common situations: Tool config URL returns truncated HTML/XML; the XML contains unescaped ampersands or invalid entities; a proxy mangles the response body; the vendor serves a partial file.
Related errors
- Invalid url in xml. Ampersands must be escaped.
- Invalid XML Configuration
- Access token expired
- Access token invalid - signature likely incorrect
- assignment_invalid
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/624feb96bb70f324.
Report an issue: GitHub.
Appendix: source
Thrown at lib/cc/importer/blti_converter.rb:120
end
if (icon = get_node_val(doc, "#{link_css_path} > #{blti}|icon"))
tool[:settings] ||= {}
tool[:settings][:icon_url] = icon.strip
end
tool
end
def convert_blti_xml(xml)
doc = create_xml_doc(xml)
unless doc.namespaces.to_s.downcase.include? "imsglobal"
raise CCImportError, I18n.t("Invalid XML Configuration")
end
begin
tool = convert_blti_link(doc)
check_for_unescaped_url_properties(tool) if tool
rescue Nokogiri::XML::XPath::SyntaxError
raise CCImportError, I18n.t(:invalid_xml_syntax, "Invalid xml syntax")
end
tool
end
def check_for_unescaped_url_properties(obj)
# Recursively look for properties named 'url'
case obj
when Hash
obj.select { |k, v| k.to_s == "url" && v.is_a?(String) }
.each_value { |v| check_for_unescaped_url(v) }
obj.each_value { |v| check_for_unescaped_url_properties(v) }
when Array
obj.each { |o| check_for_unescaped_url_properties(o) }
end
end
def check_for_unescaped_url(url)
if /(.*[^=]*\?*=)[^&;]*=/.match?(url)View on GitHub (pinned to 1c9f0bb801)