pentaho/pentaho-kettle · error · KettleXMLException

Error loading transformation step from XML

Error message

Error loading transformation step from XML

What it means

SingleThreaderMeta.loadXML deserializes the SingleThreader step's XML, including the <parameters> block where each <parameter> must supply <name> and <value> tags. Any Exception during parsing is caught and rethrown as a KettleXMLException 'Error loading transformation step from XML' with the original cause attached.

Solutions

  1. Read the chained cause to identify the exact element that failed to parse.
  2. Validate the .ktr XML and fix the <parameters> block so each <parameter> has both <name> and <value> children.
  3. Restore the step or file from backup / repository history.
  4. Recreate the SingleThreader step in Spoon and reconfigure parameters, then save a fresh copy.
  5. Check version compatibility between the Pentaho versions that wrote and read the file.

Example fix

// before: parameter missing value tag
<parameter><name>ROWS</name></parameter>
// after
<parameter><name>ROWS</name><value>1000</value></parameter>
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the parameters block before loading the transformation
Node parametersNode = XMLHandler.getSubNode(stepnode, "parameters");
int n = XMLHandler.countNodes(parametersNode, "parameter");
for (int i = 0; i < n; i++) {
  Node p = XMLHandler.getSubNodeByNr(parametersNode, "parameter", i);
  if (XMLHandler.getTagValue(p, "name") == null) {
    throw new IllegalStateException("SingleThreader parameter #" + i + " is missing a <name> tag");
  }
}

Try / catch

try {
  meta.loadXML(stepnode, databases, metaStore, variables);
} catch (KettleXMLException e) {
  logError("Failed to parse SingleThreader step XML: " + e.getMessage());
  throw new IllegalStateException("Fix or restore the .ktr parameter block", e);
}

Prevention

When it happens

Trigger: An Exception occurs in loadXML while reading the step's XML - typically while iterating parametersNode and calling XMLHandler.getTagValue on <name>/<value> children, e.g. when a <parameter> element is missing expected sub-tags or the XML is malformed.

Common situations: Hand-edited .ktr where a <parameter> tag lacks <name> or <value>; truncated/corrupted file from an interrupted save; version skew between the tool that wrote the XML and the engine reading it; bad merge in version control dropping XML tags.

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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/singlethreader/SingleThreaderMeta.java:122

      retrieveStep = XMLHandler.getTagValue( stepnode, "retrieve_step" );

      Node parametersNode = XMLHandler.getSubNode( stepnode, "parameters" );

      String passAll = XMLHandler.getTagValue( parametersNode, "pass_all_parameters" );
      passingAllParameters = Utils.isEmpty( passAll ) || "Y".equalsIgnoreCase( passAll );

      int nrParameters = XMLHandler.countNodes( parametersNode, "parameter" );

      allocate( nrParameters );

      for ( int i = 0; i < nrParameters; i++ ) {
        Node knode = XMLHandler.getSubNodeByNr( parametersNode, "parameter", i );

        parameters[i] = XMLHandler.getTagValue( knode, "name" );
        parameterValues[i] = XMLHandler.getTagValue( knode, "value" );
      }
    } catch ( Exception e ) {
      throw new KettleXMLException( BaseMessages.getString(
        PKG, "SingleThreaderMeta.Exception.ErrorLoadingTransformationStepFromXML" ), e );
    }
  }

  public void allocate( int nrParameters ) {
    parameters = new String[nrParameters];
    parameterValues = new String[nrParameters];
  }

  public Object clone() {
    SingleThreaderMeta retval = (SingleThreaderMeta) super.clone();
    int nrParameters = parameters.length;
    retval.allocate( nrParameters );
    System.arraycopy( parameters, 0, retval.parameters, 0, nrParameters );
    System.arraycopy( parameterValues, 0, retval.parameterValues, 0, nrParameters );

    return retval;
  }

View on GitHub (pinned to f3058517a1)