karatelabs/karate · warning

fromString XML parse failed

Error message

fromString XML parse failed: {}

What it means

The XML branch of karate's fromString coercion: when a string is detected as XML (StringUtils.isXml), Xml.toXmlDoc converts it to a document node. If that conversion throws, 'fromString XML parse failed' is logged and the original string is returned as-is — a non-fatal fallback so callers receive the raw text rather than an exception.

Solutions

  1. Fix the input so it is well-formed XML (close all tags, single root, valid entities).
  2. Validate the XML with a parser/linter (xmllint or Xml parsing in isolation) before passing it to fromString.
  3. If the content is HTML, escape/convert it to XHTML or use an HTML-tolerant parser instead of fromString.
  4. Read the logged e.getMessage() to find the exact malformed location in the document.
  5. Handle the fallback in caller code: check whether the result is a String vs a document and branch accordingly.

Example fix

// before
var doc = karate.fromString('<a><b>text</a>'); // mismatched tag -> warning, returns raw string

// after
var doc = karate.fromString('<a><b>text</b></a>'); // well-formed -> XML doc node
Defensive patterns

Strategy: validation

Validate before calling

// JS: well-formedness smoke test before fromString
function looksWellFormedXml(s) {
  return /^\s*<\/?[\w:-]+[\s\S]*>\s*$/.test(s) &&
    s.replace(/<\/[\w:-]+>/g, '').length !== s.length; // has at least one close tag
}

Type guard

function isXmlDoc(v) { return v !== null && typeof v === 'object' && typeof v !== 'string'; }

Try / catch

// fromString returns the raw string on XML failure; check the result type
var doc = karate.fromString(xmlText);
if (typeof doc === 'string') {
  // XML parse failed; handle malformed input explicitly
}

Prevention

When it happens

Trigger: Calling karate.fromString(...) (or a coercion path using it) with a string that looks like XML but is not well-formed: unclosed tags, mismatched tags, invalid entity references, XML declaration issues, multiple root elements, or encoding/character problems.

Common situations: Scraping XML from an upstream service that returns malformed XML; building XML by string concatenation and forgetting to close a tag; HTML (not XHTML) pasted where strict XML parsing is expected; SOAP payloads truncated by an earlier transformation.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/c98f7ccbf0d17bbe. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/KarateJsUtils.java:799

            if (args.length == 0 || args[0] == null) {
                return null;
            }
            String text = args[0].toString();
            if (text.isEmpty()) {
                return text;
            }
            if (StringUtils.looksLikeJson(text)) {
                try {
                    return Json.of(text).value();
                } catch (Exception e) {
                    logger.warn("fromString JSON parse failed: {}", e.getMessage());
                    return text;
                }
            } else if (StringUtils.isXml(text)) {
                try {
                    return Xml.toXmlDoc(text);
                } catch (Exception e) {
                    logger.warn("fromString XML parse failed: {}", e.getMessage());
                    return text;
                }
            }
            return text;
        };
    }

    /**
     * Auto-detect MIME type from data object.
     */
    static String detectMimeType(Object obj) {
        if (obj instanceof Map || obj instanceof List) {
            return "application/json";
        } else if (obj instanceof Node) {
            return "application/xml";
        } else if (obj instanceof byte[] bytes) {
            return sniffBytesMime(bytes);
        } else {

View on GitHub (pinned to a22eb90246)