pentaho/pentaho-kettle · warning · IllegalArgumentException

" + element.getName() + " has a null id

Error message

" + element.getName() + " has a null id

What it means

PurRepository.updateSharedObjectCache throws IllegalArgumentException when passed a repository element whose ObjectId or its id string is null. Cached shared objects must be identifiable by id; a null id indicates an element that was never persisted or was not properly initialized.

Solutions

  1. Call repository.save(element) first so the repository assigns an ObjectId before caching
  2. Check element.getObjectId() != null before invoking cache update paths
  3. Re-load the element from the repository instead of reusing an unpersisted in-memory copy
  4. Ensure clones preserve the ObjectId if that is intended

Example fix

// before
DatabaseMeta db = new DatabaseMeta();
repo.updateSharedObjectCache(db, RepositoryObjectType.DATABASE, db.getObjectId()); // throws
// after
DatabaseMeta db = new DatabaseMeta();
repo.save(db, null); // assigns ObjectId
if (db.getObjectId() != null) {
  repo.updateSharedObjectCache(db, RepositoryObjectType.DATABASE, db.getObjectId());
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (element != null && element.getObjectId() != null && element.getObjectId().getId() != null) {
  // safe to proceed
}

Type guard

boolean hasPersistedId(RepositoryElementInterface el) {
  return el != null && el.getObjectId() != null && el.getObjectId().getId() != null;
}

Try / catch

try {
  cacheUpdate(element, type, id);
} catch (IllegalArgumentException e) {
  if (e.getMessage().endsWith("has a null id")) {
    // persist element first, then retry
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling updateSharedObjectCache (directly or via save/update flows) with an element constructed in memory that has not been assigned an ObjectId by the repository — e.g. saving a new DatabaseMeta/PartitionSchema/SlaveServer whose id was never set.

Common situations: Creating a new shared object in code and attempting to cache/update it before calling repository.save; cloning elements that lose their id; loading elements from a non-pur repository and reusing them with a pur repository.

Related errors


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

Appendix: source

Thrown at plugins/pur/core/src/main/java/org/pentaho/di/repository/pur/PurRepository.java:2840

    }
  }

  private void updateSharedObjectCache( final RepositoryElementInterface element ) throws KettleException {
    updateSharedObjectCache( element, null, null );
  }

  private void removeFromSharedObjectCache( final RepositoryObjectType type, final ObjectId id )
    throws KettleException {
    updateSharedObjectCache( null, type, id );
  }

  /**
   * Do not call this method directly. Instead call updateSharedObjectCache or removeFromSharedObjectCache.
   */
  private void updateSharedObjectCache( final RepositoryElementInterface element, final RepositoryObjectType type,
                                        final ObjectId id ) throws KettleException {
    if ( element != null && ( element.getObjectId() == null || element.getObjectId().getId() == null ) ) {
      throw new IllegalArgumentException( element.getName() + " has a null id" );
    }

    readWriteLock.readLock().lock();
    sharedObjectsLock.writeLock().lock();

    loadAndCacheSharedObjects( false );

    boolean remove = element == null;
    ObjectId idToFind = element != null ? element.getObjectId() : id;
    RepositoryObjectType typeToUpdate = element != null ? element.getRepositoryElementType() : type;
    RepositoryElementInterface elementToUpdate = null;
    List<? extends SharedObjectInterface<?>> origSharedObjects = null;
    try {
      switch ( typeToUpdate ) {
        case DATABASE:
          origSharedObjects = sharedObjectsByType.get( RepositoryObjectType.DATABASE );
          if ( !remove ) {
            elementToUpdate = (RepositoryElementInterface) ( (DatabaseMeta) element ).deepClone( true );

View on GitHub (pinned to f3058517a1)