pentaho/pentaho-kettle · error · KettleXMLException

Error parsing XML

Error message

Error parsing XML

What it means

loadXMLString parses an XML string via the cached DocumentBuilder; when db.parse throws an IOException it is rethrown as KettleXMLException("Error parsing XML", ef). This is the I/O branch of string parsing; general exceptions fall into the broader 'Error reading information from XML string' handler.

Solutions

  1. Check e.getCause() for the underlying IOException.
  2. Retry once after XMLHandler.resetDocumentBuilder() if the cached builder was in a bad state.
  3. Validate the XML string syntactically before calling loadXMLString.
  4. Ensure the string is complete and not truncated mid-document.

Example fix

// before
Document doc = XMLHandler.loadXMLString(xmlFromSocket);
// after
if (xmlFromSocket == null || xmlFromSocket.trim().isEmpty()) {
  throw new KettleException("Empty XML payload");
}
Document doc = XMLHandler.loadXMLString(xmlFromSocket);
Defensive patterns

Strategy: try-catch

Validate before calling

if (xml == null || xml.trim().isEmpty()) throw new KettleException("Empty XML input");

Type guard

boolean looksLikeXml(String s) {
  return s != null && s.trim().startsWith("<");
}

Try / catch

try {
  doc = XMLHandler.loadXMLString(xml);
} catch (KettleXMLException e) {
  log.error("Parse failed: " + e.getCause());
}

Prevention

When it happens

Trigger: XMLHandler.loadXMLString(String) where the Reader-backed InputSource throws IOException during parse (I/O failure while reading the in-memory string reader, or certain underlying parser I/O errors).

Common situations: Very rare in practice since input is an in-memory string; usually surfaces from low-level parser failures or JVM-level IO issues.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/ccbe29865b20ae90. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/xml/XMLHandler.java:789

    if ( Boolean.TRUE.equals( deferNodeExpansion ) && ! Boolean.TRUE.equals( namespaceAware ) ) {
      return loadXMLString( DEFAULT_BUILDER_CACHE.get(), string );
    }
    // For non-default configurations, create a one-off builder
    DocumentBuilder db = createDocumentBuilder( namespaceAware, deferNodeExpansion );
    return loadXMLString( db, string );
  }

  public static Document loadXMLString( DocumentBuilder db, String string ) throws KettleXMLException {

    try {
      StringReader stringReader = new java.io.StringReader( string );
      InputSource inputSource = new InputSource( stringReader );

      Document doc;
      try {
        doc = db.parse( inputSource );
      } catch ( IOException ef ) {
        throw new KettleXMLException( "Error parsing XML", ef );
      } finally {
        resetDocumentBuilder( db );
        stringReader.close();
      }

      return doc;
    } catch ( Exception e ) {
      throw new KettleXMLException( "Error reading information from XML string : " + Const.CR + string, e );
    }
  }

  public static DocumentBuilder createDocumentBuilder( boolean namespaceAware, boolean deferNodeExpansion )
    throws KettleXMLException {
    try {
      DocumentBuilderFactory dbf = XMLParserFactoryProducer.createSecureDocBuilderFactory();
      dbf.setFeature( "http://apache.org/xml/features/dom/defer-node-expansion", deferNodeExpansion );
      dbf.setNamespaceAware( namespaceAware );
      return dbf.newDocumentBuilder();

View on GitHub (pinned to f3058517a1)