pentaho/pentaho-kettle · error · KettleXMLException

XMLHandler.errorReadingFile

XMLHandler.errorReadingFile

Error message

${XMLHandler.errorReadingFile}

What it means

XMLHandler.loadXMLFile() retries reading/parsing a file a few times (with a sleep between attempts) and, when all attempts fail with an exception, throws a KettleXMLException with message key 'XMLHandler.errorReadingFile' including the file path, wrapping the last exception.

Solutions

  1. Open and parse the file independently (e.g. with xmllint or a DocumentBuilder) to see the underlying 'lastException' cause
  2. Ensure the producing step has finished flushing/closing the file before it is read
  3. Validate the XML is well-formed and its declared encoding matches the bytes
  4. Increase availability of the file (local disk vs flaky network mount) or add your own retry with longer backoff
  5. Catch KettleXMLException and log the file path plus cause for diagnosis

Example fix

// before
Document doc = XMLHandler.loadXMLFile( fileObject );
// after
Document doc;
try {
  doc = XMLHandler.loadXMLFile( fileObject );
} catch ( KettleXMLException e ) {
  throw new KettleException( "Failed to read XML file " + fileObject.getName().getURI()
    + " after retries: " + e.getMessage(), e );
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate before calling loadXMLFile
if ( fileObject == null || !fileObject.exists() ) {
  throw new KettleException( "XML file missing: " + ( fileObject == null ? "null" : fileObject.toString() ) );
}
// optionally: bytes readable and non-empty
Content c = fileObject.getContent();
if ( c.getSize() == 0 ) { throw new KettleException( "XML file is empty" ); }

Try / catch

try {
  Document doc = XMLHandler.loadXMLFile( fileObject );
} catch ( KettleXMLException e ) {
  // message starts with resolved 'XMLHandler.errorReadingFile'; e.getCause() is lastException
  Throwable cause = e.getCause();
  throw new KettleException( "Cannot read " + fileObject + ": " + ( cause == null ? e.getMessage() : cause.getMessage() ), e );
}

Prevention

When it happens

Trigger: Calling any XMLHandler.loadXMLFile(FileObject/… variant) where the file cannot be read or parsed on every attempt — malformed XML, IO errors, encoding problems.

Common situations: File locked by another process, incomplete/partial file written by a prior step, invalid XML characters or encoding mismatch, network file system (VFS) latency causing reads to fail within the retry window.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

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

        retries = 0;
      }
      int attempts = 0;
      while ( attempts <= retries ) {
        try {
          return loadXMLFile( KettleVFS.getInputStream( fileObject ), systemID, ignoreEntities, namespaceAware );
        } catch ( Exception ex ) {
          lastException = ex;
          try {
            java.lang.Thread.sleep( 1000 );
          } catch ( InterruptedException e ) {
            //Sonar squid S2142 requires the handling of the InterruptedException instead of ignoring it
            Thread.currentThread().interrupt();
          }
        }
        attempts++;
      }

      throw new KettleXMLException( BaseMessages.getString(
        PKG, "XMLHandler.errorReadingFile", fileObject.toString() ), lastException );
    }

    throw new KettleXMLException( BaseMessages.getString(
      PKG, "XMLHandler.FileDoesNotExists", fileObject.toString() ) );
  }

  /**
   * Read in an XML file from the passed input stream and return an XML document
   *
   * @param inputStream The filename input stream to read the document from
   * @return the Document if all went well, null if an error occurred!
   */
  public static Document loadXMLFile( InputStream inputStream ) throws KettleXMLException {
    return loadXMLFile( inputStream, null, false, false );
  }

  /**

View on GitHub (pinned to f3058517a1)