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
- Call repository.save(element) first so the repository assigns an ObjectId before caching
- Check element.getObjectId() != null before invoking cache update paths
- Re-load the element from the repository instead of reusing an unpersisted in-memory copy
- 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
- Always repository.save() new elements before cache/update operations
- Check getObjectId() after save — it is assigned by the repository
- Avoid reusing elements loaded from a different repository implementation
- Ensure clone() implementations preserve ObjectId where intended
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
- unknown type [" + typeToUpdate + "]
- Could not retrieve version history of object with path
- DELETE_JOB : repository is read-only
- ERROR_0002_Cannot_Load_Job_From_Repository
- FuzzyMatchMeta.Exception.UnexpecteErrorReadingStepInfoFromRe…
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)