Common errors
NoRootMappingError
Error message:
Lutaml::Model::NoRootMappingError: ModelName has `no_root`, it is allowed only for reusable models
Cause:
Attempting to parse a type-only model directly instead of through a parent model.
Solution:
Type-only models (without element() or root()) can only be parsed when embedded:
# This will fail
class Address < Lutaml::Model::Serializable
xml do
# No element declaration - type-only
map_element 'street', to: :street
end
end
Address.from_xml(xml) # NoRootMappingError!
# Solution: Parse through parent model
class Contact < Lutaml::Model::Serializable
attribute :address, Address
xml do
element 'contact'
map_element 'address', to: :address
end
end
Contact.from_xml(xml) # Works!NoRootNamespaceError
Error message:
Lutaml::Model::NoRootNamespaceError: Namespaces are not supported with `no_root`
Cause:
Using namespace with no_root or type-only models.
Solution:
Remove namespace from type-only models, or add element declaration:
# This will fail
class Address < Lutaml::Model::Serializable
xml do
no_root
namespace 'https://example.com/address', 'addr' # Not allowed!
map_element 'street', to: :street
end
end
# Solution 1: Remove namespace (type-only)
class Address < Lutaml::Model::Serializable
xml do
# No namespace, no element
sequence do
map_element 'street', to: :street
end
end
end
# Solution 2: Add element declaration
class Address < Lutaml::Model::Serializable
xml do
element 'address' # Now it has an element
namespace 'https://example.com/address', 'addr'
map_element 'street', to: :street
end
endIncorrectSequenceError
Error message:
Lutaml::Model::IncorrectSequenceError: Element `city` does not match the expected sequence order element `street`
Cause:
Elements in XML appear in different order than defined in sequence block.
Solution:
Ensure XML elements match sequence order, or remove sequence if order doesn’t matter:
class Person < Lutaml::Model::Serializable
xml do
element 'person'
sequence do
map_element 'name', to: :name # Must appear first
map_element 'email', to: :email # Must appear second
end
end
end
# This works:
valid_xml = "<person><name>John</name><email>j@ex.com</email></person>"
# This fails:
invalid_xml = "<person><email>j@ex.com</email><name>John</name></person>"
# IncorrectSequenceError!
# Solution: Fix XML order or remove sequence
class Person < Lutaml::Model::Serializable
xml do
element 'person'
# No sequence - elements can appear in any order
map_element 'name', to: :name
map_element 'email', to: :email
end
endInvalidFormatError
Error message:
Lutaml::Model::InvalidFormatError: Invalid XML format
Cause:
Malformed XML input that cannot be parsed by the adapter.
Solution:
Validate XML syntax before parsing, or handle the error gracefully:
begin
model = MyModel.from_xml(xml_string)
rescue Lutaml::Model::InvalidFormatError => e
puts "XML is malformed: #{e.message}"
# Log error, return default, or re-raise as appropriate
endUnknownAdapterTypeError
Error message:
Lutaml::Model::UnknownAdapterTypeError: Unknown XML adapter type: :invalid
Cause:
XML adapter not configured or invalid adapter type specified.
Solution:
Configure XML adapter before use:
# Add this to your initialization code
Lutaml::Model::Config.configure do |config|
config.xml_adapter_type = :nokogiri # or :ox, :oga
endNamespace issues
Type-level namespace not applied
Problem:
Custom type has namespace declared but element isn’t qualified in output.
Check:
-
Verify namespace directive is on the Type class itself (not instance)
-
Ensure namespace is declared before type is used
-
Check if explicit mapping namespace is overriding
# Wrong: namespace on wrong class level
class MyType < Lutaml::Model::Type::String
def initialize
namespace MyNamespace # WRONG - this is instance-level
end
end
# Correct: namespace as class directive
class MyType < Lutaml::Model::Type::String
namespace MyNamespace # CORRECT - class-level directive
xsd_type 'MyCustomType'
end
# Check: child model class namespace overrides type namespace
class Value < Lutaml::Model::Serializable
attribute :content, :string
xml do
element 'value'
namespace OtherNamespace # Model-level namespace
map_content to: :content
end
end
class Model < Lutaml::Model::Serializable
attribute :value, Value # Uses Value's namespace
xml do
element 'model'
map_element 'value', to: :value
end
endType namespace not recognized during parsing
Problem:
Deserialization fails to match namespace-qualified elements to types.
Check:
-
Ensure Type namespace is defined identically in both directions
-
Verify namespace URI matches exactly (prefixes don’t matter)
-
Check adapter is configured correctly
# Namespace URIs must match exactly
class DcNamespace < Lutaml::Model::XmlNamespace
uri 'http://purl.org/dc/elements/1.1/' # Check: no trailing slash?
prefix_default 'dc'
end
# Input XML must use same URI
xml = <<~XML
<doc:document xmlns:doc="..." xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title>Test</dc:title>
</document>
XML
# Verify round-trip
parsed = Document.from_xml(xml)
puts parsed.to_xml # Should match input namespacesWrong namespace URI in output
Problem:
Generated XML has unexpected or missing namespace.
Check:
-
Verify namespace URI in XmlNamespace class
-
Check if namespace is actually referenced in model or type
-
Ensure adapter is configured
# Verify namespace definition
class MyNamespace < Lutaml::Model::XmlNamespace
uri 'https://example.com/correct/uri' # Check this
prefix_default 'correct'
end
# Verify namespace is used (model-level)
class Model < Lutaml::Model::Serializable
xml do
element 'model'
namespace MyNamespace # Must reference the class
map_element 'attr', to: :attr
end
end
# Or verify namespace is used (type-level)
class CustomType < Lutaml::Model::Type::String
namespace MyNamespace # Type-level namespace
end
class Model < Lutaml::Model::Serializable
attribute :attr, CustomType
xml do
element 'model'
map_element 'attr', to: :attr # Uses MyNamespace from CustomType
end
endNamespace prefix mismatch
Problem:
XML has different prefix than expected.
Remember:
Prefixes are just labels - URI is what matters. These are equivalent:
<contact:person xmlns:contact="https://example.com/contact">
<c:person xmlns:c="https://example.com/contact">If you need specific prefix:
# Set default
class ContactNamespace < Lutaml::Model::XmlNamespace
prefix_default 'contact' # Preferred prefix
end
# Or override at runtime
class Model < Lutaml::Model::Serializable
xml do
element 'model'
namespace ContactNamespace, 'c' # Override to 'c'
end
endElements not qualified when expected
Problem:
Child elements don’t have namespace prefix.
Check qualification settings:
class MyNamespace < Lutaml::Model::XmlNamespace
uri 'https://example.com/schema'
prefix_default 'pfx'
element_form_default :unqualified # ← This is why!
end
# Solution 1: Change namespace to :qualified
class MyNamespace < Lutaml::Model::XmlNamespace
uri 'https://example.com/schema'
prefix_default 'pfx'
element_form_default :qualified # Now children are qualified
end
# Solution 2: Use child model class for specific elements
class ChildValue < Lutaml::Model::Serializable
attribute :value, :string
xml do
element 'child'
namespace MyNamespace # Model-level namespace
map_content to: :value
end
end
class Model < Lutaml::Model::Serializable
attribute :child, ChildValue
xml do
element 'model'
namespace MyNamespace
map_element 'child', to: :child # Uses ChildValue's namespace
end
end
# Solution 3: Use Type-level namespace for specific elements
class ChildType < Lutaml::Model::Type::String
xml_namespace MyNamespace # This element always qualified
end
class Model < Lutaml::Model::Serializable
attribute :child, ChildType
xml do
element 'model'
map_element 'child', to: :child # Qualified via ChildType
end
endParsing issues
Mixed content not preserved
Problem:
Text between elements is lost during parsing.
Solution:
Enable mixed content mode:
class RichText < Lutaml::Model::Serializable
xml do
root 'text', mixed: true # Enable mixed content
map_element 'b', to: :bold
map_element 'i', to: :italic
end
end
# Or use explicit method
class RichText < Lutaml::Model::Serializable
xml do
element 'text'
mixed_content # Explicit declaration
map_element 'b', to: :bold
map_element 'i', to: :italic
end
endElement order not preserved
Problem:
Elements appear in different order after round-trip.
Solution:
Use ordered: true or sequence:
# Option 1: ordered flag
class Model < Lutaml::Model::Serializable
xml do
root 'model', ordered: true
map_element 'first', to: :first
map_element 'second', to: :second
end
end
# Option 2: sequence (also enforces order on parsing)
class Model < Lutaml::Model::Serializable
xml do
element 'model'
sequence do
map_element 'first', to: :first
map_element 'second', to: :second
end
end
endAttributes not parsed
Problem:
XML attributes are missing after parsing.
Check mapping:
# Wrong: using map_element for attribute
class Model < Lutaml::Model::Serializable
xml do
element 'model'
map_element 'id', to: :id # Wrong for XML attribute!
end
end
# Correct: use map_attribute
class Model < Lutaml::Model::Serializable
xml do
element 'model'
map_attribute 'id', to: :id # Correct for XML attribute
end
endXSD generation issues
XSD missing namespace declarations
Problem:
Generated XSD doesn’t include namespace declarations.
Solution:
Pass namespace options to Schema.to_xml:
# Won't include targetNamespace
xsd = Lutaml::Model::Schema.to_xml(Model)
# Includes proper namespace declarations
xsd = Lutaml::Model::Schema.to_xml(
Model,
namespace: MyNamespace.uri,
prefix: MyNamespace.prefix_default
)Type names incorrect in XSD
Problem:
Generated XSD has unexpected type names.
Solution:
Use type_name to override default inference:
class Product < Lutaml::Model::Serializable
xml do
element 'product'
type_name 'CatalogItemType' # Override default 'ProductType'
end
endXSD missing documentation
Problem:
Generated XSD has no annotations.
Solution:
Add documentation to namespace and models:
class MyNamespace < Lutaml::Model::XmlNamespace
uri 'https://example.com/schema'
documentation "Schema description" # Namespace-level
end
class Model < Lutaml::Model::Serializable
xml do
element 'model'
namespace MyNamespace
documentation "Model description" # Type-level
end
endEncoding issues
Corrupted characters in output
Problem:
Non-ASCII characters appear as `` or hex codes.
Solution:
Set encoding explicitly:
# For Japanese text
instance = JapaneseCeramic.new(glaze_type: "志野釉")
instance.encoding = "UTF-8" # Explicit encoding
xml = instance.to_xml
# Or per-export
xml = instance.to_xml(encoding: "UTF-8")Wrong encoding in XML declaration
Problem:
XML declaration has wrong encoding attribute.
Solution:
Encoding is controlled by instance or export settings:
# Instance-level (affects all exports from this instance)
instance.encoding = "Shift_JIS"
# Per-export (overrides instance encoding)
xml = instance.to_xml(encoding: "UTF-8")Adapter-specific issues
Ox adapter with special characters
Issue:
Ox uses ASCII-8bit by default, may corrupt UTF-8.
Solution:
Always specify encoding when using Ox with UTF-8:
Lutaml::Model::Config.configure do |config|
config.xml_adapter_type = :ox
end
# Always specify encoding
xml = model.to_xml(encoding: "UTF-8")
parsed = Model.from_xml(xml, encoding: "UTF-8")Tomlib segfault on Windows
Issue:
Tomlib adapter can segfault on invalid TOML (Windows, Ruby < 3.3).
Mitigation:
-
Validate TOML before parsing
-
Or use toml-rb adapter instead
-
Or upgrade to Ruby 3.3+
Lutaml::Model::Config.configure do |config|
config.toml_adapter_type = :toml_rb # Safer on older Ruby/Windows
endPerformance issues
Slow XML parsing
Diagnosis:
Check which adapter you’re using.
Solution:
Switch to faster adapter if possible:
# Ox is fastest
Lutaml::Model::Config.configure do |config|
config.xml_adapter_type = :ox
end
# Nokogiri is good balance
Lutaml::Model::Config.configure do |config|
config.xml_adapter_type = :nokogiri
end
# Oga is pure Ruby (slowest but no native deps)
Lutaml::Model::Config.configure do |config|
config.xml_adapter_type = :oga
endDebugging techniques
Enable verbose output
Check what’s happening:
# Add debug output in custom methods
def custom_from_xml(model, value)
puts "Parsing: #{value.inspect}"
model.attr = process(value)
endInspect parsed structure
View intermediate results:
model = Model.from_xml(xml)
# Check attribute values
puts model.inspect
# Check internal instance variables
puts model.instance_variables
# For custom methods, inspect value parameter
def custom_from_xml(model, value)
pp value # Pretty print the value hash
# value typically has: {"text" => [...], "elements" => {...}}
endVerify namespace matching
Check namespace URIs:
model = Model.from_xml(xml)
# If using schema_location metadata
if model.respond_to?(:schema_location)
puts model.schema_location.inspect
end
# Check the XML output
puts model.to_xml
# Verify xmlns declarations match expectationsTest round-trip
Verify consistency:
original = Model.new(attr: "value")
xml = original.to_xml
parsed = Model.from_xml(xml)
if original == parsed
puts "Round-trip successful"
else
puts "Round-trip failed!"
puts "Original: #{original.inspect}"
puts "Parsed: #{parsed.inspect}"
# Use diff to see differences
require 'pp'
diff_score, diff_tree = Lutaml::Model::Serialize.diff_with_score(
original,
parsed
)
puts "Difference: #{(diff_score * 100).round(2)}%"
puts diff_tree
endConfiguration issues
Adapter not found
Problem:
NameError: uninitialized constant Lutaml::Model::Xml::OxAdapter
Cause:
Adapter gem not installed.
Solution:
Install required gem:
# For Ox
gem install ox
# or add to Gemfile: gem 'ox'
# For Oga
gem install oga
# or add to Gemfile: gem 'oga'
# Nokogiri usually already installed
gem install nokogiriConfiguration not applied
Problem:
Adapter configuration seems ignored.
Check:
Configuration must happen before first model use:
# WRONG: Configure after using models
Model.from_xml(xml) # Uses default adapter
Lutaml::Model::Config.configure do |config|
config.xml_adapter_type = :ox # Too late!
end
# CORRECT: Configure early
Lutaml::Model::Config.configure do |config|
config.xml_adapter_type = :ox
end
Model.from_xml(xml) # Uses OxGetting help
Check existing documentation
-
Main README:
README.adoc -
Core concepts: [
docs/xml_mappings/02_core_concepts.adoc](02_core_concepts.adoc) -
Common patterns: [
docs/xml_mappings/05_common_patterns.adoc](05_common_patterns.adoc)
Deprecation warnings
Type::Value.namespace is deprecated
Symptom:
Deprecation warning when using namespace directive on Type::Value classes:
[DEPRECATION] Type::Value.namespace is deprecated. Use xml_namespace instead.
This will be removed in version 1.0.0Cause:
Using the old namespace directive instead of xml_namespace for Type::Value classes.
Solution:
Replace namespace with xml_namespace:
class DcTitleType < Lutaml::Model::Type::String
namespace DublinCoreNamespace # ⚠️ DEPRECATED
xsd_type 'titleType'
endclass DcTitleType < Lutaml::Model::Type::String
xml_namespace DublinCoreNamespace # ✅ CURRENT
xsd_type 'titleType'
endWhy the change?
The namespace directive is reserved for future semantic namespace features (JSON-LD, RDF). The unified xml do … end block provides clear, XML-specific configuration.
No functional changes: The behavior is identical, only the directive name changed.
See also:
-
README.adoc- Type-level namespace documentation -
[
docs/xml_mappings/04_xml_namespace_class.adoc](04_xml_namespace_class.adoc#migration-from-deprecated-namespace-directive)-
Complete migration guide
-
-
[
docs/xml_mappings/06_migration_guide.adoc](06_migration_guide.adoc#deprecated-syntax-migration)-
Deprecated syntax migration section
-