Skip to content

Troubleshooting

The CLI exits with status 1 and prints nothing

The CLI catches every exception and calls sys.exit(1). Validation failures happen before any logging, so they leave no message. Check these causes in order:

  1. The input file does not exist. The path is relative to the current directory.

    ls -l guide.md
    
  2. A language code is invalid. Codes must be two lowercase ASCII letters. EN, en-US, pt_BR and deu all fail.

    vexy-markliff md2xliff guide.md guide.xlf --source_lang=en --target_lang=de
    
  3. The input is empty or contains only whitespace.

To see the actual exception, call the converter from Python, where it is not swallowed:

from pathlib import Path
from vexy_markliff import VexyMarkliff

text = Path("guide.md").read_text(encoding="utf-8")
VexyMarkliff().markdown_to_xliff(text, "en", "de")

The traceback names the exception (ValidationError, ConversionError) and its message, for example Invalid target language code: EN.

The CLI exits with status 1 and logs a parse error

Errors raised inside the conversion step are logged before the exit, for example:

Failed to parse XLIFF XML: Couldn't find end of Start Tag bad line 1, line 2, column 1 (<string>, line 2)
XLIFF to Markdown conversion failed: Invalid XLIFF XML: ...

The input for xliff2md or xliff2html is not well-formed XML. Check it with an XML validator or python -c "from lxml import etree; etree.parse('file.xlf')".

xliff2md writes an empty file

The command succeeded but found no units. The reader looks only for <trans-unit> elements in the namespace urn:oasis:names:tc:xliff:document:2.1. Files from other tools usually use the XLIFF 2.x structure (<unit>, <segment>) or the XLIFF 1.2 namespace (urn:oasis:names:tc:xliff:document:1.2), and both yield zero units.

Only files written by vexy-markliff itself are read correctly. See XLIFF output.

The translated text does not appear after converting back

xliff2md and xliff2html use the <source> text of each unit and ignore <target>. This is a limitation of version 1.3. To get the translations out, read the targets with the models:

from pathlib import Path
from vexy_markliff.models.xliff import XLIFFDocument

doc = XLIFFDocument.from_xml(Path("guide.de.xlf").read_text(encoding="utf-8"))
for unit in doc.files[0].units:
    print(unit.id, unit.target or unit.source)

A sentence is split across several units

Inline markup splits text. Save **now** please becomes three units: Save, now, please. The extractor works on lxml text nodes and does not yet use inline codes (<mrk>, <ph>). The planned behaviour is described in HTML mapping rules.

Script, style or code text appears in the XLIFF

The extractor takes every text node, including <script>, <style>, <pre> and <code> content. Remove such content before conversion, or drop the matching units afterwards.

The reverse conversion writes one <p> per unit and has no record of the original element. Keep the original document; version 1.3 cannot rebuild it from the XLIFF.

The configuration file has no effect

ConversionConfig.load() reads source_language, target_language and split_sentences from YAML, but the CLI has no option to load it, and the converter does not read the values. Pass language codes as method arguments or CLI flags.

ConversionConfig.load() also returns the default configuration, without raising, when the file is missing or contains an invalid value. If your settings seem ignored when you use it directly, inspect the returned object:

from vexy_markliff import ConversionConfig

config = ConversionConfig.load("vexy-markliff.yaml")
print(config.source_language, config.target_language, config.split_sentences)

__version__ is unknown

vexy_markliff/__version__.py is generated by hatch-vcs when the package is built or installed. A bare source checkout on sys.path does not have it. Install the package (uv pip install -e .) to generate it.

The examples/ scripts fail with ModuleNotFoundError

The scripts in examples/ import modules such as vexy_markliff.core.element_classifier and vexy_markliff.core.format_style, which were removed when the code base was simplified. They do not run against version 1.3. Use the snippets in Quick start and Python API instead.