pentaho/pentaho-kettle · error · KettleObjectExistsException

Failed to create object in repository. Object

Error message

Failed to create object in repository. Object [{name}] already exists.

What it means

KettleObjectExistsException thrown by the private insertCluster method when the cluster schema name is already present in the repository at insert time. It is a last-resort guard inside saveClusterSchema: even if the higher-level collision check passed, the insert re-verifies uniqueness before generating a new id. This keeps repository names unique under concurrency.

Solutions

  1. Retry the save operation, which will now detect the existing object and take the update path
  2. Use repository.deleteClusterSchema on the conflicting id if the new object should replace it
  3. Rename the cluster schema to a unique name before saving
  4. Serialize repository writes (the method is synchronized; avoid bypassing saveClusterSchema)

Example fix

// before
ObjectId id = repository.save(clusterSchema, "v1", new Date(), false); // may race

// after
try {
  id = repository.save(clusterSchema, "v1", new Date(), true);
} catch (KettleObjectExistsException e) {
  clusterSchema.setName(clusterSchema.getName() + "-" + System.currentTimeMillis());
  id = repository.save(clusterSchema, "v1", new Date(), false);
}
Defensive patterns

Strategy: retry

Validate before calling

if (repository.getClusterSchemaID(clusterSchema.getName()) != null) { clusterSchema.setName(clusterSchema.getName() + "_" + UUID.randomUUID()); }

Type guard

boolean insertable = repository.getClusterSchemaID(name) == null;

Try / catch

try { repository.save(cs, label, date, false); } catch (KettleObjectExistsException e) { cs.setName(uniqueName()); repository.save(cs, label, date, false); }

Prevention

When it happens

Trigger: insertCluster invoked (via saveClusterSchema) while another thread/session has just created a cluster schema with the same name, so getClusterID(name) returns non-null right before insert.

Common situations: Two developers or two import jobs inserting identically-named cluster schemas concurrently; race between the duplicate check and the insert.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/repository/kdr/delegates/KettleDatabaseRepositoryClusterSchemaDelegate.java:148

      if ( slaveServer.getObjectId() == null ) {
        // oops, not yet saved!

        repository.save( slaveServer, versionComment, null, id_transformation, isUsedByTransformation, overwrite );
      }
      repository.insertClusterSlave( clusterSchema, slaveServer );
    }

    // Save a link to the transformation to keep track of the use of this cluster schema
    // Only save it if it's really used by the transformation
    if ( isUsedByTransformation ) {
      repository.insertTransformationCluster( id_transformation, clusterSchema.getObjectId() );
    }
  }

  private synchronized ObjectId insertCluster( ClusterSchema clusterSchema ) throws KettleException {
    if ( getClusterID( clusterSchema.getName() ) != null ) {
      // This cluster schema name is already in use. Throw an exception.
      throw new KettleObjectExistsException( "Failed to create object in repository. Object ["
        + clusterSchema.getName() + "] already exists." );
    }

    ObjectId id = repository.connectionDelegate.getNextClusterID();

    RowMetaAndData table = new RowMetaAndData();

    table.addValue( new ValueMetaInteger(
      KettleDatabaseRepository.FIELD_CLUSTER_ID_CLUSTER ), id );
    table.addValue(
      new ValueMetaString( KettleDatabaseRepository.FIELD_CLUSTER_NAME ),
      clusterSchema.getName() );
    table.addValue( new ValueMetaString(
      KettleDatabaseRepository.FIELD_CLUSTER_BASE_PORT ), clusterSchema
      .getBasePort() );
    table
      .addValue(
        new ValueMetaString(

View on GitHub (pinned to f3058517a1)