pentaho/pentaho-kettle · error · KettleXMLException

UserDefinedJavaClassMeta.Exception.UnableToLoadStepInfoFromX…

Error message

UserDefinedJavaClassMeta.Exception.UnableToLoadStepInfoFromXML

What it means

UserDefinedJavaClassMeta.readData, invoked from loadXML when deserializing the UDJC step from a .ktr XML file, wraps any exception while parsing definitions/usage parameters into KettleXMLException with key UserDefinedJavaClassMeta.Exception.UnableToLoadStepInfoFromXML. It means the step's XML fragment could not be loaded.

Solutions

  1. Open the transformation in the same or newer Pentaho version that produced it.
  2. Inspect the UDJC step's XML node for missing/corrupt child elements and repair or re-create the step.
  3. Check the root cause (the wrapped exception 'e' in the stack trace) for the exact XMLHandler failure, e.g. a missing tag value.

Example fix

// XML before (missing required child)
<definitions><class_name>MyClass</class_name></definitions>
// after: include all expected elements or re-save the step in Spoon
<definitions><class_type>TRANSFORM_CLASS</class_type><class_name>MyClass</class_name><class_source>...</class_source></definitions>
Defensive patterns

Strategy: try-catch

Validate before calling

// before loading, sanity-check the UDJC XML fragment
String xml = XMLHandler.getTagValue(stepNode, "definitions"); if (xml == null) throw new KettleXMLException("UDJC step XML missing 'definitions' node");

Type guard

boolean hasUdjcXml(Node stepNode) { return XMLHandler.getTagValue(stepNode, "definitions") != null; }

Try / catch

try { meta.loadXML(stepNode, databases, metaStore); } catch (KettleXMLException e) { logError("Failed to load UDJC step from XML", e); throw e; }

Prevention

When it happens

Trigger: Malformed or unexpected XML in the UDJC step node — missing/renamed element tags, incompatible XML produced by a newer Pentaho version, or corrupted transformation files.

Common situations: Opening a transformation created in a newer Pentaho/Kettle version in an older one (XML schema drift); hand-edited .ktr files; truncated/corrupted repository exports.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/userdefinedjavaclass/UserDefinedJavaClassMeta.java:408

        stepDefinition.stepName = XMLHandler.getTagValue( targetNode, ElementNames.step_name.name() );
        stepDefinition.description = XMLHandler.getTagValue( targetNode, ElementNames.step_description.name() );
        targetStepDefinitions.add( stepDefinition );
      }

      usageParameters.clear();
      Node parametersNode = XMLHandler.getSubNode( stepnode, ElementNames.usage_parameters.name() );
      int nrParameters = XMLHandler.countNodes( parametersNode, ElementNames.usage_parameter.name() );
      for ( int i = 0; i < nrParameters; i++ ) {
        Node parameterNode = XMLHandler.getSubNodeByNr( parametersNode, ElementNames.usage_parameter.name(), i );
        UsageParameter usageParameter = new UsageParameter();
        usageParameter.tag = XMLHandler.getTagValue( parameterNode, ElementNames.parameter_tag.name() );
        usageParameter.value = XMLHandler.getTagValue( parameterNode, ElementNames.parameter_value.name() );
        usageParameter.description =
          XMLHandler.getTagValue( parameterNode, ElementNames.parameter_description.name() );
        usageParameters.add( usageParameter );
      }
    } catch ( Exception e ) {
      throw new KettleXMLException( BaseMessages.getString(
        PKG, "UserDefinedJavaClassMeta.Exception.UnableToLoadStepInfoFromXML" ), e );
    }
  }

  public void setDefault() {
    // Moved the default code generation out of Meta since the Snippits class is in the UI package which isn't in the
    // classpath.
  }

  private boolean checkClassCookings( LogChannelInterface logChannel ) {
    boolean ok = cookedTransformClass != null && cookErrors.size() == 0;
    if ( changed ) {
      cookClasses();
      if ( cookedTransformClass == null ) {
        if ( cookErrors.size() > 0 ) {
          logChannel.logDebug( BaseMessages.getString(
            PKG, "UserDefinedJavaClass.Exception.CookingError", cookErrors.get( 0 ) ) );
        }

View on GitHub (pinned to f3058517a1)