pentaho/pentaho-kettle · error · KettleException
Error saving database connection or one of its attributes…
Error message
Error saving database connection or one of its attributes to the repository.
What it means
Wraps a KettleDatabaseException thrown while persisting a DatabaseMeta and its attributes to the repository (insert/update of R_DATABASE plus delete/re-insert of its attribute rows). The save is not applied and the cause carries the database-level error.
Solutions
- Inspect the wrapped KettleDatabaseException for the failing statement
- Ensure the connection name is unique in R_DATABASE or update the existing entry instead of inserting
- Verify the repository DB is writable and the session connection is healthy
- Clean duplicate/orphan R_DATABASE_ATTRIBUTE rows for the connection id, then retry
Example fix
// before
rep.save(repoMeta, "my-connection"); // may duplicate/conflict
// after: reuse existing id if the connection already exists
ObjectId existing = databaseDelegate.getDatabaseID("my-connection");
databaseMeta.setObjectId(existing); // null => insert, otherwise update
databaseDelegate.saveDatabaseMeta(databaseMeta); Defensive patterns
Strategy: validation
Validate before calling
// ensure name uniqueness before saving
PreparedStatement ps = conn.prepareStatement("SELECT COUNT(*) FROM R_DATABASE WHERE NAME = ?");
ps.setString(1, databaseMeta.getName());
if (rsCount(ps) > 0) { databaseMeta.setObjectId(databaseDelegate.getDatabaseID(databaseMeta.getName())); } Try / catch
try {
delegate.saveDatabaseMeta(databaseMeta);
} catch (KettleException e) {
log.error("Save of database connection failed", e.getCause());
// check constraints, writability, then retry
} Prevention
- Use unique connection names across environments
- Verify repository DB is writable before bulk operations
- Clean orphaned attribute rows after failed saves
When it happens
Trigger: Calling saveDatabaseMeta(databaseMeta) when any insert/update of R_DATABASE, or delDatabaseAttributes/insertDatabaseAttributes, throws: constraint violation, SQL error, or lost connection.
Common situations: Saving a connection with a name that conflicts with an existing entry; repository DB read-only or quota exceeded; connection dropped mid-save; duplicate attribute rows from a previously failed save.
Related errors
- ERROR_0003_Cannot_Save_Job_Entry
- ERROR_0003_Cannot_Save_Job_Entry
- ERROR_0003_Cannot_Save_Job_Entry
- ERROR_0003_Unable_To_Save_Job
- Error loading database connection from repository
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/9a077cd281fcd9d3.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/repository/kdr/delegates/KettleDatabaseRepositoryDatabaseDelegate.java:195
} else {
// --> found entry with the same name...
// Update the note...
updateDatabase(
databaseMeta.getObjectId(), databaseMeta.getName(), databaseMeta.getPluginId(), DatabaseMeta
.getAccessTypeDesc( databaseMeta.getAccessType() ), databaseMeta.getHostname(), databaseMeta
.getDatabaseName(), databaseMeta.getDatabasePortNumberString(), databaseMeta.getUsername(),
databaseMeta.getPassword(), databaseMeta.getServername(), databaseMeta.getDataTablespace(),
databaseMeta.getIndexTablespace() );
}
// For the extra attributes, just delete them and re-add them.
delDatabaseAttributes( databaseMeta.getObjectId() );
// OK, now get a list of all the attributes set on the database connection...
insertDatabaseAttributes( databaseMeta.getObjectId(), databaseMeta.getAttributes() );
} catch ( KettleDatabaseException dbe ) {
throw new KettleException(
"Error saving database connection or one of its attributes to the repository.", dbe );
}
}
public synchronized ObjectId insertDatabase( String name, String type, String access, String host,
String dbname, String port, String user, String pass, String servername, String data_tablespace,
String index_tablespace ) throws KettleException {
ObjectId id = repository.connectionDelegate.getNextDatabaseID();
ObjectId id_database_type = getDatabaseTypeID( type );
if ( id_database_type == null ) {
// New support database type: add it!
id_database_type = repository.connectionDelegate.getNextDatabaseTypeID();
String tablename = KettleDatabaseRepository.TABLE_R_DATABASE_TYPE;
RowMetaInterface tableMeta = new RowMeta();View on GitHub (pinned to f3058517a1)