pentaho/pentaho-kettle · error · KettleException
JobTrans.Exception.MetaDataLoad
Error message
JobTrans.Exception.MetaDataLoad
What it means
This is the catch-all wrapper at the end of getMetaForEntry: any non-KettleException thrown while resolving, loading, caching, or variable-reseeding the referenced meta (TransMeta/JobMeta) is wrapped in a KettleException whose message is the localized 'JobTrans.Exception.MetaDataLoad' (metadata load failure). The original exception is preserved as the cause. It signals that loading the child transformation/job metadata failed for an unexpected reason — I/O errors, parsing failures, repository errors, NPEs, etc.
Solutions
- Inspect the wrapped cause (KettleException.getCause()) — it names the real failure (file not found, parse error, repo error).
- Verify the referenced file path / repository object still exists and is readable; re-select the reference in Spoon and re-save the job.
- Validate the ktr/kjb XML opens cleanly in Spoon; fix or regenerate corrupted metadata.
- Ensure required VFS/connection plugins are installed and the process has filesystem permissions for the referenced path.
- Wrap the call site in try/catch (KettleException ke) and log ke.getCause() for diagnostics before retrying or failing the parent job.
Example fix
// before
theMeta = jobEntryLoader.getMetaForEntry( bowl, rep, metaStore, space ); // opaque MetaDataLoad failure
// after
try {
theMeta = jobEntryLoader.getMetaForEntry( bowl, rep, metaStore, space );
} catch ( KettleException ke ) {
logError( "Loading job entry metadata failed: " + ke.getMessage(), ke.getCause() );
throw ke;
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check the referenced artifact exists and is readable before loading
String path = jobEntry.getFilename();
if ( path != null && !new File( path ).canRead() ) {
throw new FileNotFoundException( "Referenced metadata not readable: " + path );
} Type guard
boolean metaLoadable( Repository rep, JobEntryInterface e, VariableSpace space ) {
switch ( e.getSpecificationMethod() ) {
case FILENAME: return e.getFilename() != null && new File( space.environmentSubstitute( e.getFilename() ) ).canRead();
case REPOSITORY_BY_REFERENCE: return rep != null && e.getObjectId() != null;
case REPOSITORY_BY_NAME: return rep != null && e.getName() != null;
default: return false;
}
} Try / catch
try {
meta = loader.getMetaForEntry( bowl, rep, metaStore, space );
} catch ( KettleException ke ) {
Throwable cause = ke.getCause();
logError( "Metadata load failed: " + ke.getMessage() + " caused by " + cause, cause );
if ( cause instanceof FileNotFoundException || cause instanceof IOException ) {
throw new JobExecutionException( "Referenced transformation/job file missing or unreadable", ke );
}
throw ke;
} Prevention
- Always inspect getCause() — this error is a wrapper and the root cause names the real problem.
- Verify referenced ktr/kjb files exist at execution time (paths can move between environments).
- Install required VFS plugins (pvfs/hdfs/s3) on every runtime node.
- Open referenced metadata in Spoon periodically to catch corruption early.
- Check filesystem permissions for the service account running Kitchen.
When it happens
Trigger: Any unexpected Exception inside getMetaForEntry: unreadable or malformed ktr/kjb file in FILENAME mode, repository load throwing a non-Kettle RuntimeException, errors in attemptLoadMeta/getMetaFromRepository, ClassCastException, or failures in reseedInternalDirectoryVars/cacheMeta.
Common situations: Referenced transformation file deleted or moved after the job was authored; corrupt or partially written ktr/kjb XML; missing VFS plugins (pvfs/hdfs) so file resolution throws; permission errors reading the file; repository connectivity flakiness surfacing as a raw exception.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- GPBulkLoaderMeta.Exception.ErrorGettingFields
- JobEntryMSAccessBulkLoad.Meta.UnableLoadRep
- JobEntryMSAccessBulkLoad.Meta.UnableLoadXML
- SynchronizeAfterMergeMeta.Exception.ErrorGettingFields
- AbsSecurityManager.ERROR_0004_UNABLE_TO_APPLY_LOGICAL_ROLES_TO_RUNTIME_ROLE
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/12973f3b640fd55a.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/base/MetaFileLoaderImpl.java:284
}
break;
default:
throw new KettleException( "The specified object location specification method '"
+ specificationMethod + "' is not yet supported in this " + friendlyMetaType + " entry." );
}
cacheMeta( idContainer[ 0 ], theMeta );
// Re-seed the internal directory variables on the returned meta from the freshly resolved tmpSpace.
// The cache may return an instance whose internal vars were last set in a different context
// (e.g. from a step loader using getVarSpaceOnlyWithRequiredParentVars, or with rep==null),
// which would otherwise leak the wrong Internal.Entry.Current.Directory into the child execution.
reseedInternalDirectoryVars( theMeta, tmpSpace );
return theMeta;
} catch ( final KettleException ke ) {
// if we get a KettleException, simply re-throw it
throw ke;
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString( persistentClass, "JobTrans.Exception.MetaDataLoad" ), e );
}
}
/**
* Force the four internal directory variables on the loaded meta to the values resolved by
* {@link CurrentDirectoryResolver} for *this* job-entry invocation. Without this, a cached
* TransMeta/JobMeta returned from a previous load can carry stale Internal.Entry.Current.Directory
* (and friends) inherited from whatever space was active during that earlier load.
*/
private void reseedInternalDirectoryVars( T theMeta, VariableSpace tmpSpace ) {
if ( theMeta == null || tmpSpace == null || !( theMeta instanceof org.pentaho.di.base.AbstractMeta ) ) {
return;
}
org.pentaho.di.base.AbstractMeta meta = (org.pentaho.di.base.AbstractMeta) theMeta;
String entryDir = tmpSpace.getVariable( INTERNAL_VARIABLE_ENTRY_CURRENT_DIRECTORY );
if ( entryDir != null ) {
meta.setVariable( INTERNAL_VARIABLE_ENTRY_CURRENT_DIRECTORY, entryDir );
}View on GitHub (pinned to f3058517a1)