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

  1. Inspect the wrapped KettleDatabaseException for the failing statement
  2. Ensure the connection name is unique in R_DATABASE or update the existing entry instead of inserting
  3. Verify the repository DB is writable and the session connection is healthy
  4. 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

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


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)