pentaho/pentaho-kettle · error · KettleException
ERROR0003.UnableToSaveStepToRepository
ERROR0003.UnableToSaveStepToRepository
Error message
DatabaseLookupMeta.ERROR0003.UnableToSaveStepToRepository
What it means
DatabaseLookupMeta.saveRep() wraps any exception raised while persisting the step's attributes (or inserting the step-database relationship) into a KettleException 'Unable to save step information to the repository' + idStep, so a failed transformation save names the offending step.
Solutions
- Inspect the nested cause for the underlying repository/SQL error
- Ensure the step's DatabaseMeta is saved first (non-null ObjectId) before saving the step
- Verify the repository user has write permissions and the DB is writable/reachable
- Retry the transformation save after restoring connectivity
Example fix
// before
if ( databaseMeta != null ) {
rep.insertStepDatabase( idTransformation, idStep, databaseMeta.getObjectId() );
}
// after
if ( databaseMeta != null ) {
if ( databaseMeta.getObjectId() == null ) {
rep.save( databaseMeta, idTransformation, metaStore );
}
rep.insertStepDatabase( idTransformation, idStep, databaseMeta.getObjectId() );
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-save checks
if ( !rep.isConnected() ) throw new KettleException( "Repository not connected" );
if ( meta.getDatabaseMeta() != null && meta.getDatabaseMeta().getObjectId() == null ) {
rep.save( meta.getDatabaseMeta(), transMeta.getObjectId(), metaStore );
} Try / catch
try {
transMeta.saveRep( rep, metaStore, transId );
} catch ( KettleException e ) {
if ( e.getMessage() != null && e.getMessage().contains( "Unable to save step information" ) ) {
logError( "Save failed for step " + e.getMessage() + "; cause=" + e.getCause(), e );
} else { throw e; }
} Prevention
- Save dependent DatabaseMetas before saving steps
- Use a repository login with write access
- Check repository disk space/connection stability for large saves
- Read getCause() to identify the failing attribute write
When it happens
Trigger: Saving a transformation to a repository when rep.saveStepAttribute* fails, rep.insertStepDatabase fails (databaseMeta set but its ObjectId is null or the step row cannot be written), or the repository connection drops.
Common situations: Read-only repository credentials; interrupted saves leaving partial rows; an in-memory DatabaseMeta never stored so getObjectId() is null; repository DB out of space or connection dropped.
Related errors
- AnalyticQueryMeta.Exception.UnexpectedErrorInReadingStepInfo…
- AnalyticQueryMeta.Exception.UnableToSaveStepInfoToRepository
- DatabaseJoinMeta.Exception.UnableToSaveStepInfo + id_step
- DimensionLookupMeta.Exception.UnexpectedErrorReadingStepInfo…
- Unable to load shared objects
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/e13972d3eebc370a.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/databaselookup/DatabaseLookupMeta.java:629
rep.saveStepAttribute( idTransformation, idStep, i, TAG_LOOKUP_KEY_FIELD, tableKeyField[ i ] );
rep.saveStepAttribute( idTransformation, idStep, i, TAG_LOOKUP_KEY_CONDITION, keyCondition[ i ] );
rep.saveStepAttribute( idTransformation, idStep, i, TAG_LOOKUP_KEY_NAME2, streamKeyField2[ i ] );
}
for ( int i = 0; i < returnValueField.length; i++ ) {
rep.saveStepAttribute( idTransformation, idStep, i, TAG_RETURN_VALUE_NAME, returnValueField[ i ] );
rep.saveStepAttribute( idTransformation, idStep, i, TAG_RETURN_VALUE_RENAME, returnValueNewName[ i ] );
rep.saveStepAttribute( idTransformation, idStep, i, TAG_RETURN_VALUE_DEFAULT, returnValueDefault[ i ] );
rep.saveStepAttribute( idTransformation, idStep, i, TAG_RETURN_VALUE_TYPE, ValueMetaFactory
.getValueMetaName( returnValueDefaultType[ i ] ) );
}
// Also, save the step-database relationship!
if ( databaseMeta != null ) {
rep.insertStepDatabase( idTransformation, idStep, databaseMeta.getObjectId() );
}
} catch ( Exception e ) {
throw new KettleException(
BaseMessages.getString( PKG, "DatabaseLookupMeta.ERROR0003.UnableToSaveStepToRepository" ) + idStep, e );
}
}
@Override
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 ) {
try ( Database db = new Database( loggingObject, databaseMeta ) ) {
db.shareVariablesWith( transMeta );
databases = new Database[] { db }; // Keep track of this one for cancelQuery
db.connect();
if ( !Utils.isEmpty( tablename ) ) {View on GitHub (pinned to f3058517a1)