pentaho/pentaho-kettle · error · KettleException
DetectLastRowMeta.Exception.UnableToSaveStepInfo
DetectLastRowMeta.Exception.UnableToSaveStepInfo
Error message
DetectLastRowMeta.Exception.UnableToSaveStepInfo
What it means
DetectLastRowMeta.saveRep wraps any exception while saving the step's attributes to a Kettle repository into a KettleException with this localized message plus the step id. The underlying repository write failure is chained as the cause.
Solutions
- Inspect the chained cause for the underlying database/repository error
- Verify the repository is writable and has free space
- Re-save after reconnecting to the repository
- Shorten or sanitize the result field name if a database constraint is the cause
Example fix
// before
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString( PKG, "DetectLastRowMeta.Exception.UnableToSaveStepInfo" ) + id_step, e );
}
// after: log full cause before rethrowing
} catch ( Exception e ) {
logError( "Unable to save DetectLastRow step " + id_step, e );
throw new KettleException( BaseMessages.getString( PKG, "DetectLastRowMeta.Exception.UnableToSaveStepInfo" ) + id_step, e );
} Defensive patterns
Strategy: try-catch
Validate before calling
// before saving, verify repository is connected and writable
if ( repository == null || !repository.isConnected() ) {
throw new KettleException("Repository not connected; cannot save transformation");
} Try / catch
try {
repository.save(transMeta, versionComment, null, metaStore);
} catch (KettleException e) {
if (e.getMessage() != null && e.getMessage().contains("UnableToSaveStepInfo")) {
log.error("Save failed for DetectLastRow step; cause: " + e.getCause(), e);
}
throw e;
} Prevention
- Ensure repository database is writable with sufficient space
- Avoid invalid characters in result field names
- Save regularly so a failure isolates recent changes
- Log the chained cause, not just the wrapper message
When it happens
Trigger: Saving a transformation containing a DetectLastRow step when rep.saveStepAttribute throws: repository connection lost, read-only database, constraint violation, or oversized attribute value.
Common situations: Repository database read-only or out of disk space; network interruption during save; saving across incompatible Pentaho versions; invalid result field name values hitting database constraints.
Related errors
- CubeInputMeta.Exception.UnableToSaveStepInfo
- CubeOutputMeta.Exception.UnableToSaveStepInfo
- CubeOutputMeta.Exception.UnexpectedErrorInReadingStepInfo
- DelayMeta.Exception.UnexpectedErrorReadingStepInfo
- DelayMeta.Exception.UnexpectedErrorSavingStepInfo
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/2e8a8f5da851747a.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/detectlastrow/DetectLastRowMeta.java:125
throw new KettleXMLException( BaseMessages.getString(
PKG, "DetectLastRowMeta.Exception.UnableToReadStepInfo" ), e );
}
}
public void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ) throws KettleException {
try {
resultfieldname = rep.getStepAttributeString( id_step, "resultfieldname" );
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString(
PKG, "DetectLastRowMeta.Exception.UnexpectedErrorReadingStepInfo" ), e );
}
}
public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step ) throws KettleException {
try {
rep.saveStepAttribute( id_transformation, id_step, "resultfieldname", resultfieldname );
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString( PKG, "DetectLastRowMeta.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 = "";
if ( Utils.isEmpty( resultfieldname ) ) {
error_message = BaseMessages.getString( PKG, "DetectLastRowMeta.CheckResult.ResultFieldMissing" );
cr = new CheckResult( CheckResult.TYPE_RESULT_ERROR, error_message, stepMeta );
remarks.add( cr );
} else {
error_message = BaseMessages.getString( PKG, "DetectLastRowMeta.CheckResult.ResultFieldOK" );
cr = new CheckResult( CheckResult.TYPE_RESULT_OK, error_message, stepMeta );
remarks.add( cr );View on GitHub (pinned to f3058517a1)