pentaho/pentaho-kettle · error · KettleException

ExecSQLRowMeta.Exception.UnableToSaveStepInfo

Error message

ExecSQLRowMeta.Exception.UnableToSaveStepInfo

What it means

KettleException thrown by ExecSQLRowMeta.saveRep() when saving the step's attributes to the repository fails, with id_step appended to the message. It wraps exceptions thrown by rep.saveStepAttribute() or rep.insertStepDatabase() calls.

Solutions

  1. Save the referenced database connection first so it has a valid ObjectId, then save the step.
  2. Check getCause() for the JDBC-level write error (permissions, constraint, space).
  3. Confirm repository user has write access to the target folder.
  4. Retry after resolving lock/availability issues on the repository DB.

Example fix

// before
rep.save(stepMeta.getStepMetaInterface(), ...); // db connection not persisted
// after
if (databaseMeta.getObjectId() == null) {
  rep.save(databaseMeta, null);
}
meta.saveRep(rep, metaStore, transMeta.getObjectId(), stepMeta.getObjectId());
Defensive patterns

Strategy: try-catch

Validate before calling

if (databaseMeta.getObjectId() == null) rep.save(databaseMeta, null); // persist connection first

Try / catch

try { meta.saveRep(rep, metaStore, id_trans, id_step); } catch (KettleException e) { log.error("repository write failed: " + e.getCause(), e); }

Prevention

When it happens

Trigger: saveRep() fails on rep.insertStepDatabase() or any rep.saveStepAttribute(id_transformation, id_step, ...) — repository write error, invalid database meta reference, lost connection, or read-only repository.

Common situations: Referenced database connection not yet saved (null ObjectId); repository quota/disk full; concurrent modification conflict; insufficient repository permissions.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/execsqlrow/ExecSQLRowMeta.java:349

    try {
      rep.saveDatabaseMetaStepAttribute( id_transformation, id_step, "id_connection", databaseMeta );
      rep.saveStepAttribute( id_transformation, id_step, "commit", commitSize );
      rep.saveStepAttribute( id_transformation, id_step, "sql_field", sqlField );

      rep.saveStepAttribute( id_transformation, id_step, "insert_field", insertField );
      rep.saveStepAttribute( id_transformation, id_step, "update_field", updateField );
      rep.saveStepAttribute( id_transformation, id_step, "delete_field", deleteField );
      rep.saveStepAttribute( id_transformation, id_step, "read_field", readField );

      // Also, save the step-database relationship!
      if ( databaseMeta != null ) {
        rep.insertStepDatabase( id_transformation, id_step, databaseMeta.getObjectId() );
      }

      rep.saveStepAttribute( id_transformation, id_step, "sqlFromfile", sqlFromfile );
      rep.saveStepAttribute( id_transformation, id_step, "sendOneStatement", sendOneStatement );
    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString( PKG, "ExecSQLRowMeta.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;

    if ( databaseMeta != null ) {
      cr =
        new CheckResult( CheckResult.TYPE_RESULT_OK, BaseMessages.getString(
          PKG, "ExecSQLRowMeta.CheckResult.ConnectionExists" ), stepMeta );
      remarks.add( cr );

      Database db = new Database( loggingObject, databaseMeta );
      databases = new Database[] { db }; // keep track of it for cancelling purposes...

View on GitHub (pinned to f3058517a1)