pentaho/pentaho-kettle · error · KettleXMLException

JobDosToUnix.Error.Exception.UnableLoadXML

Error message

JobDosToUnix.Error.Exception.UnableLoadXML

What it means

Thrown when the XML for a 'DOS to Unix' job entry cannot be parsed in loadXML(), e.g. while reading its file/wildcard/ConversionType fields. It wraps the original KettleXMLException. Means the job entry's XML block is malformed or structurally unexpected.

Solutions

  1. Validate the .kjb file XML (xmllint) and repair the DosToUnix entry's <fields> block
  2. Recreate/re-export the job entry from Spoon
  3. Align Pentaho versions between file producer and consumer
  4. Check the chained 'xe' cause for the exact parse error location

Example fix

// before
entry.loadXML(entrynode, databases, slaveServers, rep, metaStore); // raw KettleXMLException
// after
try {
  entry.loadXML(entrynode, databases, slaveServers, rep, metaStore);
} catch (KettleXMLException e) {
  logError("DosToUnix XML invalid: " + e.getMessage());
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

Document doc = XMLHandler.loadXMLFile(new File(kjbPath));
if (doc == null) throw new IllegalArgumentException("Invalid XML: " + kjbPath);
Node entry = XMLHandler.getSubNode(doc.getDocumentElement(), "entry");
if (XMLHandler.getSubNode(entry, "fields") == null) {
  throw new IllegalArgumentException("DosToUnix entry missing <fields>");
}

Type guard

boolean isEntryNode(Node node) {
  return node != null && "entry".equals(node.getNodeName());
}

Try / catch

try {
  entry.loadXML(entrynode, databases, slaveServers, rep, metaStore);
} catch (KettleXMLException e) {
  logError("DosToUnix XML parse failed: " + e.getMessage(), e.getCause());
  throw e;
}

Prevention

When it happens

Trigger: Calling loadXML() (via loading a .kjb file or fromXMLString) where XMLHandler.getSubNodeByNr/getTagValue raises KettleXMLException on the entry's <fields>/<field> structure.

Common situations: Corrupted or hand-edited .kjb files; files written by an incompatible Pentaho/Kettle version; wrong node passed to loadXML; truncated export.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/job/entries/dostounix/JobEntryDosToUnix.java:243

      Node fields = XMLHandler.getSubNode( entrynode, "fields" );

      // How many field arguments?
      int nrFields = XMLHandler.countNodes( fields, "field" );
      allocate( nrFields );

      // Read them all...
      for ( int i = 0; i < nrFields; i++ ) {
        Node fnode = XMLHandler.getSubNodeByNr( fields, "field", i );

        source_filefolder[i] = XMLHandler.getTagValue( fnode, "source_filefolder" );
        wildcard[i] = XMLHandler.getTagValue( fnode, "wildcard" );
        conversionTypes[i] =
          getConversionTypeByCode( Const.NVL( XMLHandler.getTagValue( fnode, "ConversionType" ), "" ) );
      }
    } catch ( KettleXMLException xe ) {

      throw new KettleXMLException(
        BaseMessages.getString( PKG, "JobDosToUnix.Error.Exception.UnableLoadXML" ), xe );
    }
  }

  public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases,
    List<SlaveServer> slaveServers ) throws KettleException {
    try {
      arg_from_previous = rep.getJobEntryAttributeBoolean( id_jobentry, "arg_from_previous" );
      include_subfolders = rep.getJobEntryAttributeBoolean( id_jobentry, "include_subfolders" );

      nr_errors_less_than = rep.getJobEntryAttributeString( id_jobentry, "nr_errors_less_than" );
      success_condition = rep.getJobEntryAttributeString( id_jobentry, "success_condition" );
      resultfilenames = rep.getJobEntryAttributeString( id_jobentry, "resultfilenames" );

      // How many arguments?
      int argnr = rep.countNrJobEntryAttributes( id_jobentry, "source_filefolder" );
      allocate( argnr );

View on GitHub (pinned to f3058517a1)