langchain-ai/langchain · error · OutputParserException

Failed to parse XML format from completion {text}. Got: {e}

Error message

Failed to parse XML format from completion {text}. Got: {e}

What it means

OutputParserException raised by XMLOutputParser.parse when et.fromstring raises ParseError: after extracting optional fenced code blocks and encoding declarations and stripping whitespace, the text is still not well-formed XML. The original text is attached via llm_output for debugging.

Source

Thrown at libs/core/langchain_core/output_parsers/xml.py:251

            et = ElementTree  # Use the defusedxml parser
        else:
            et = ET  # Use the standard library parser

        match = re.search(r"```(xml)?(.*)```", text, re.DOTALL)
        if match is not None:
            # If match found, use the content within the backticks
            text = match.group(2)
        encoding_match = self.encoding_matcher.search(text)
        if encoding_match:
            text = encoding_match.group(2)

        text = text.strip()
        try:
            root = et.fromstring(text)
            return self._root_to_dict(root)
        except et.ParseError as e:
            msg = f"Failed to parse XML format from completion {text}. Got: {e}"
            raise OutputParserException(msg, llm_output=text) from e

    @override
    def _transform(self, input: Iterator[str | BaseMessage]) -> Iterator[AddableDict]:
        streaming_parser = _StreamingParser(self.parser)
        for chunk in input:
            yield from streaming_parser.parse(chunk)
        streaming_parser.close()

    @override
    async def _atransform(
        self, input: AsyncIterator[str | BaseMessage]
    ) -> AsyncIterator[AddableDict]:
        streaming_parser = _StreamingParser(self.parser)
        async for chunk in input:
            for output in streaming_parser.parse(chunk):
                yield output
        streaming_parser.close()

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Use XMLOutputParser's get_format_instructions()/prompt template so the model sees the exact expected format and encoding
  2. Increase max_tokens so closing tags are not truncated
  3. Catch OutputParserException, inspect llm_output, and retry with corrective feedback or strip non-XML prefix/suffix before re-parsing

Example fix

# before
prompt = "Give me people and their favorite foods in XML."
chain = prompt | llm | XMLOutputParser()

# after
parser = XMLOutputParser()
prompt = PromptTemplate(
    template="Answer the user query.\n{format_instructions}\n{query}",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)
chain = prompt | llm | parser
Defensive patterns

Strategy: retry

Validate before calling

import re

def looks_like_xml(text: str) -> bool:
    text = text.strip()
    m = re.search(r"```(?:xml)?(.*)```", text, re.DOTALL)
    if m:
        text = m.group(1)
    return bool(re.search(r"<[a-zA-Z:_][^>]*>", text))

Try / catch

from langchain_core.exceptions import OutputParserException
try:
    out = parser.invoke(text)
except OutputParserException as e:
    raw = e.llm_output  # original text for repair
    out = parser.invoke(f"<filtered>{strip_non_xml(raw)}</filtered>")  # repair & retry

Prevention

When it happens

Trigger: LLM returns malformed XML: unclosed tags, XML-ish prose without a single root element, markdown bullet fragments like '- <tag>value' where '-' precedes the root, multiple sibling root elements, or unescaped & characters.

Common situations: Prompting 'return XML' without an example; models wrapping XML in explanations; truncation by max_tokens cutting the closing tag; special characters (&, <) not escaped in values.

Understand the failure class

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/6e6a7372c21ba5e5. Report an issue: GitHub.