pentaho/pentaho-kettle · error · KettleXMLException

JobExecutorMeta.Exception.ErrorLoadingJobExecutorDetailsFromXML

JobExecutorMeta.Exception.ErrorLoadingJobExecutorDetailsFromXML

Error message

JobExecutorMeta.Exception.ErrorLoadingJobExecutorDetailsFromXML

What it means

Thrown by JobExecutorMeta.loadXML when deserializing the step's metadata from a .ktr XML file: any Exception raised while parsing the step's XML node (result rows fields, result files settings, group field, etc.) is wrapped in a KettleXMLException with this generic message. The underlying parse failure is the cause.

Solutions

  1. Open the .ktr in a text editor and inspect the JobExecutor step's XML node for malformed or truncated tags; fix or restore from backup/Version History
  2. Check the 'Caused by' of the KettleXMLException to locate the exact tag that failed to parse
  3. Recreate the JobExecutor step in Spoon and reconfigure it instead of repairing the XML manually
  4. Regenerate or re-export the transformation from the source system to get valid XML

Example fix

// before (hand-edited XML, broken tag)
<result_rows_field>
  <name>amount</name>
  <type>Number</type
</result_rows_field>   <!-- unclosed type tag -->
// after
<result_rows_field>
  <name>amount</name>
  <type>Number</type>
</result_rows_field>
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the .ktr XML parses and contains the JobExecutor step node before loading
Document doc = XMLHandler.loadXMLFile(ktrFile);
Node stepnode = XMLHandler.getSubNode(
  XMLHandler.getSubNode(doc, "transformation"), "step");
if ( stepnode == null ) throw new IllegalStateException("Invalid or missing step XML in " + ktrFile);

Type guard

boolean isLoadableKtr(File ktrFile) {
  try {
    Document doc = XMLHandler.loadXMLFile(ktrFile);
    return doc != null && XMLHandler.getSubNode(doc, "transformation") != null;
  } catch ( Exception e ) { return false; }
}

Try / catch

try {
  transMeta = new TransMeta(ktrFile, metaStore);
} catch ( KettleXMLException e ) {
  logError("Failed loading JobExecutor step details from XML: " + e.getMessage());
  // inspect e.getCause() for the exact XML parse failure, then restore/recreate the step
  Throwable cause = e.getCause();
  if ( cause != null ) logError("Underlying XML error: " + cause.getMessage());
}

Prevention

When it happens

Trigger: Loading a transformation whose JobExecutor step XML node is malformed or contains values that fail conversion (e.g. Const.toInt on a non-numeric 'length'/'precision' tag is tolerated, but structural XML errors, missing nodes, or invalid XML overall throw here).

Common situations: Hand-edited .ktr files; transformations generated by scripts or third-party tools with wrong tag structure; XML truncated/corrupted during transfer; opening a file saved by a much newer Pentaho version with schema changes; repository import of damaged XML.

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/b978c5659d036a8d. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/jobexecutor/JobExecutorMeta.java:339

      resultRowsField = new String[nrFields];
      resultRowsType = new int[nrFields];
      resultRowsLength = new int[nrFields];
      resultRowsPrecision = new int[nrFields];

      for ( int i = 0; i < nrFields; i++ ) {

        Node fieldNode = XMLHandler.getSubNodeByNr( stepnode, "result_rows_field", i );

        resultRowsField[i] = XMLHandler.getTagValue( fieldNode, "name" );
        resultRowsType[i] = ValueMetaFactory.getIdForValueMeta( XMLHandler.getTagValue( fieldNode, "type" ) );
        resultRowsLength[i] = Const.toInt( XMLHandler.getTagValue( fieldNode, "length" ), -1 );
        resultRowsPrecision[i] = Const.toInt( XMLHandler.getTagValue( fieldNode, "precision" ), -1 );
      }

      resultFilesTargetStep = XMLHandler.getTagValue( stepnode, "result_files_target_step" );
      resultFilesFileNameField = XMLHandler.getTagValue( stepnode, "result_files_file_name_field" );
    } catch ( Exception e ) {
      throw new KettleXMLException( BaseMessages.getString(
        PKG, "JobExecutorMeta.Exception.ErrorLoadingJobExecutorDetailsFromXML" ), e );
    }
  }

  @Override
  public void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ) throws KettleException {
    String method = rep.getStepAttributeString( id_step, "specification_method" );
    specificationMethod = ObjectLocationSpecificationMethod.getSpecificationMethodByCode( method );
    String jobId = rep.getStepAttributeString( id_step, "job_object_id" );
    jobObjectId = Utils.isEmpty( jobId ) ? null : new StringObjectId( jobId );
    jobName = rep.getStepAttributeString( id_step, "job_name" );
    fileName = rep.getStepAttributeString( id_step, "filename" );
    directoryPath = rep.getStepAttributeString( id_step, "directory_path" );

    groupSize = rep.getStepAttributeString( id_step, "group_size" );
    groupField = rep.getStepAttributeString( id_step, "group_field" );
    groupTime = rep.getStepAttributeString( id_step, "group_time" );

View on GitHub (pinned to f3058517a1)