pentaho/pentaho-kettle · error · KettleException

DatabaseJoinMeta.Exception.UnexpectedErrorReadingStepInfo

Error message

DatabaseJoinMeta.Exception.UnexpectedErrorReadingStepInfo

What it means

DatabaseJoinMeta.readRep() wraps any exception thrown while reading this step's attributes (sql field, parameters, parameter fields/types, outer join flag) from a Kettle repository into a KettleException with message 'Unexpected error reading step info'. The library throws it because repository attribute access can fail in many opaque ways (repo down, missing step id, corrupt attributes) and it wants to preserve the cause chain.

Solutions

  1. Check the cause (e) attached to the KettleException — it names the real repository or ValueMetaFactory failure
  2. Verify the repository connection and that the transformation/step ObjectIds exist in the repository
  3. Confirm the 'parameter_type' attribute values stored for the step are valid Kettle value-type names
  4. Re-save the transformation from the designer to rewrite the step attributes

Example fix

// before
parameterType[i] = ValueMetaFactory.getIdForValueMeta( stype );
// after
Integer id = ValueMetaFactory.getIdForValueMeta( stype );
if ( id == null || id < 0 ) {
  logError( "Unknown parameter_type '" + stype + "' for parameter " + i + ", defaulting to String" );
  id = ValueMetaInterface.TYPE_STRING;
}
parameterType[i] = id;
Defensive patterns

Strategy: try-catch

Validate before calling

// before loading from repository
if ( rep == null || id_step == null ) throw new IllegalArgumentException( "Repository and id_step are required" );
// check connectivity
rep.connect();

Type guard

// verify stored type name parses before readRep paths consume it
boolean isValidType( String stype ) {
  try { return stype != null && ValueMetaFactory.getIdForValueMeta( stype ) != null; }
  catch ( Exception e ) { return false; }
}

Try / catch

try {
  transMeta = TransMetaFactory.loadFromRepository( rep, transId );
} catch ( KettleException e ) {
  if ( e.getMessage() != null && e.getMessage().contains( "reading step info" ) ) {
    logError( "DatabaseJoin step attributes unreadable; cause=" + e.getCause(), e );
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling readRep() (directly or via transformation deserialization from a repository) when Repository.getStepAttributeString/getStepAttributeInteger throws — e.g. id_step does not exist, the repository connection is broken, or ValueMetaFactory.getIdForValueMeta fails on an unknown stored 'parameter_type' string.

Common situations: Loading a transformation whose DatabaseJoin step was saved by a newer/older Kettle version with an unrecognized type name; a stale or dropped repository row; repository server temporarily unreachable.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/databasejoin/DatabaseJoinMeta.java:369

  public void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ) throws KettleException {
    try {
      databaseMeta = rep.loadDatabaseMetaFromStepAttribute( id_step, "id_connection", databases );
      rowLimit = (int) rep.getStepAttributeInteger( id_step, "rowlimit" );
      sql = rep.getStepAttributeString( id_step, "sql" );
      outerJoin = rep.getStepAttributeBoolean( id_step, "outer_join" );
      replacevars = rep.getStepAttributeBoolean( id_step, "replace_vars" );

      int nrparam = rep.countNrStepAttributes( id_step, "parameter_field" );

      allocate( nrparam );

      for ( int i = 0; i < nrparam; i++ ) {
        parameterField[i] = rep.getStepAttributeString( id_step, i, "parameter_field" );
        String stype = rep.getStepAttributeString( id_step, i, "parameter_type" );
        parameterType[i] = ValueMetaFactory.getIdForValueMeta( stype );
      }
    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString(
        PKG, "DatabaseJoinMeta.Exception.UnexpectedErrorReadingStepInfo" ), e );
    }
  }

  @Override
  public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step ) throws KettleException {
    try {
      rep.saveDatabaseMetaStepAttribute( id_transformation, id_step, "id_connection", databaseMeta );
      rep.saveStepAttribute( id_transformation, id_step, "rowlimit", rowLimit );
      rep.saveStepAttribute( id_transformation, id_step, "sql", sql );
      rep.saveStepAttribute( id_transformation, id_step, "outer_join", outerJoin );
      rep.saveStepAttribute( id_transformation, id_step, "replace_vars", replacevars );

      for ( int i = 0; i < parameterField.length; i++ ) {
        rep.saveStepAttribute( id_transformation, id_step, i, "parameter_field", parameterField[i] );
        rep.saveStepAttribute( id_transformation, id_step, i, "parameter_type", ValueMetaFactory
            .getValueMetaName( parameterType[i] ) );
      }

View on GitHub (pinned to f3058517a1)