pentaho/pentaho-kettle · error · KettleException

JobJob.Exception.ReferencedTransformationIdIsNull

Error message

JobJob.Exception.ReferencedTransformationIdIsNull

What it means

Same validation branch as the previous error: when specificationMethod is REPOSITORY_BY_REFERENCE and metaObjectId is null, getMetaForEntry throws a KettleException whose message key is chosen by entry type. This index corresponds to the else-branch message 'JobJob.Exception.ReferencedTransformationIdIsNull', used when the entry wraps a nested JOB (not a transformation). The meaning is identical: by-reference mode requires a non-null repository object ID.

Solutions

  1. Resolve and set the nested job's ObjectId: entry.setObjectId(rep.getJobId(name, directory)) (or the ObjectId from rep.getObjectInformation) before execution.
  2. Alternatively reference the nested job by name (REPOSITORY_BY_NAME with directory/name set) or by file path (FILENAME).
  3. Re-open and re-save the job in Spoon, re-selecting the referenced job to restore the stored object ID.
  4. Audit migrated repositories for by-reference entries with missing IDs and remap them to the target repository's IDs.

Example fix

// before
jobEntryJob.setSpecificationMethod( SPECIFICATION_METHOD.REPOSITORY_BY_REFERENCE );
// metaObjectId == null -> 'ReferencedTransformationIdIsNull'

// after
ObjectId id = rep.getJobId( "NestedJob", "/production" );
jobEntryJob.setSpecificationMethod( SPECIFICATION_METHOD.REPOSITORY_BY_REFERENCE );
jobEntryJob.setObjectId( id );
Defensive patterns

Strategy: validation

Validate before calling

// validate nested-job entries before running the parent job
for ( JobEntryCopy c : jobMeta.getJobCopies() ) {
  JobEntryInterface e = c.getEntry();
  if ( e.getSpecificationMethod() == SPECIFICATION_METHOD.REPOSITORY_BY_REFERENCE
       && e.getObjectId() == null ) {
    throw new IllegalStateException( "Nested job entry '" + e.getName() + "' has a null repository object ID" );
  }
}

Type guard

boolean hasResolvableJobReference( JobEntryInterface e ) {
  switch ( e.getSpecificationMethod() ) {
    case FILENAME: return e.getFilename() != null;
    case REPOSITORY_BY_NAME: return e.getDirectoryName() != null && e.getName() != null;
    case REPOSITORY_BY_REFERENCE: return e.getObjectId() != null;
    default: return false;
  }
}

Try / catch

try {
  meta = loader.getMetaForEntry( bowl, rep, metaStore, space );
} catch ( KettleException ke ) {
  logError( "Nested job reference unresolved: " + ke.getMessage(), ke );
  throw ke; // KettleException is rethrown as-is by the loader
}

Prevention

When it happens

Trigger: getMetaForEntry invoked for a JobEntryJob (isTransMeta() == false) configured with specificationMethod = REPOSITORY_BY_REFERENCE while metaObjectId is null — e.g. the nested-job entry was never linked to an actual repository job object.

Common situations: A 'Job' job entry pointing at a repository job by reference whose ID was dropped during copy/paste, export/import between repositories, or programmatic job construction; hand-edited kjb files missing the reference id; CI/CD pipelines that assemble jobs dynamically without resolving the target object's ObjectId.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/base/MetaFileLoaderImpl.java:247

                  ? (T) new TransMeta( bowl, metaPath, metaStore, null, true, jobEntryBase.getParentVariableSpace(),
                                       null )
                  : getMetaFromRepository( bowl, rep, r, metaPath, tmpSpace );
              } else {
                theMeta = getMetaFromRepository( bowl, rep, r, metaPath, tmpSpace );
              }
              if ( theMeta != null ) {
                idContainer[ 0 ] = metaPath;
              }
            }
          }
          break;
        case REPOSITORY_BY_REFERENCE:
          if ( metaObjectId == null ) {
            if ( isTransMeta() ) {
              throw new KettleException( BaseMessages.getString( persistentClass,
                "JobTrans.Exception.ReferencedTransformationIdIsNull" ) );
            } else {
              throw new KettleException( BaseMessages.getString( persistentClass,
                "JobJob.Exception.ReferencedTransformationIdIsNull" ) );
            }
          }

          if ( rep != null ) {
            theMeta = attemptCacheRead( metaObjectId.toString() ); //try to get from the cache first
            if ( theMeta == null ) {
              // Load the last revision
              if ( isTransMeta() ) {
                theMeta = (T) rep.loadTransformation( metaObjectId, null );
              } else {
                theMeta = (T) rep.loadJob( metaObjectId, null );
              }
              idContainer[ 0 ] = metaObjectId.toString();
            }
          } else {
            throw new KettleException(
              "Could not execute " + friendlyMetaType + " specified in a repository since we're not connected to one" );

View on GitHub (pinned to f3058517a1)