pentaho/pentaho-kettle · error · KettleException

DynamicSQLRowMeta.Exception.UnableToSaveStepInfo

Error message

DynamicSQLRowMeta.Exception.UnableToSaveStepInfo

What it means

Kettle wraps any exception thrown while persisting the Dynamic SQL Row step's settings to a repository into this KettleException, appending the step id. The failing block includes saving step attributes and insertStepDatabase for the step's database connection.

Solutions

  1. Check the cause exception; verify the repository connection is writable and still alive.
  2. Ensure the step's database connection is defined and saved (has a valid ObjectId) before saving the transformation.
  3. Save the database connection metadata first, then the transformation.
  4. Re-run the save after restoring repository connectivity; check repository disk/permission issues.

Example fix

// before: saving a step with an unsaved DB connection
stepMeta.getDatabaseMeta(); // exists only in memory, ObjectId == null
transMeta.saveRep(repo);
// after: persist the connection first
if (databaseMeta.getObjectId() == null) {
  repo.save(databaseMeta, null, false);
}
repo.save(transMeta, "comment", null);
Defensive patterns

Strategy: try-catch

Validate before calling

// before saving
if (databaseMeta != null && databaseMeta.getObjectId() == null) {
  repo.save(databaseMeta, null, false);
}

Try / catch

try { transMeta.saveRep(repo); } catch (KettleException e) { log.error("Step info save failed for step " + id_step, e.getCause()); }

Prevention

When it happens

Trigger: saveRep during transformation save: rep.saveStepAttribute(...) or rep.insertStepDatabase(...) throws (repository write failure, FK violation because the database connection is not saved, or databaseMeta.getObjectId() is null).

Common situations: Saving a transformation whose step references a database connection that was never persisted (null ObjectId); repository read-only permissions; connection dropped between read and save; shared-object inconsistencies.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/dynamicsqlrow/DynamicSQLRowMeta.java:309

    }
  }

  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 );
      rep.saveStepAttribute( id_transformation, id_step, "sql_fieldname", sqlfieldname );
      rep.saveStepAttribute( id_transformation, id_step, "query_only_on_change", queryonlyonchange );

      // Also, save the step-database relationship!
      if ( databaseMeta != null ) {
        rep.insertStepDatabase( id_transformation, id_step, databaseMeta.getObjectId() );
      }
    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString( PKG, "DynamicSQLRowMeta.Exception.UnableToSaveStepInfo" )
        + id_step, e );
    }
  }

  public void check( List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta,
    RowMetaInterface prev, String[] input, String[] output, RowMetaInterface info, VariableSpace space,
    Repository repository, IMetaStore metaStore ) {
    CheckResult cr;
    String error_message = "";

    // See if we have input streams leading to this step!
    if ( input.length > 0 ) {
      cr =
        new CheckResult( CheckResult.TYPE_RESULT_OK, BaseMessages.getString(
          PKG, "DynamicSQLRowMeta.CheckResult.ReceivingInfo" ), stepMeta );
      remarks.add( cr );
    } else {
      cr =

View on GitHub (pinned to f3058517a1)