pentaho/pentaho-kettle · error · KettleException
JobExecutorMeta.Exception.UnableToLoadJob
JobExecutorMeta.Exception.UnableToLoadJob
Error message
JobExecutorMeta.Exception.UnableToLoadJob
What it means
JobExecutorMeta.exportResources() throws this KettleException when it fails to load the sub-job referenced by the Job Executor step during transformation export. The wrapping catch re-throws any exception from resolving/loading the job specification (by filename, repository reference, or direct definition), including the fileName that could not be loaded as a message parameter. It signals the referenced job metadata could not be turned into a JobMeta object.
Solutions
- Verify the job file at the path stored in the Job Executor step (fileName) exists and is readable before exporting.
- Re-open the step settings and re-select the job so the specification method and filename/reference are re-resolved.
- Use ${Internal.Transformation.Filename.Directory}-relative paths instead of absolute paths so exports remain portable.
- If the job is repository-based, connect to the correct repository and confirm the job object still exists under the stored id_path.
- Open the referenced .kjb in Spoon to confirm it parses (a corrupt/incompatible job file also triggers this).
Example fix
// before ( Spoon, absolute path )
JobExecutorMeta meta = ...;
meta.setFileName( "/home/dev/jobs/run_etl.kjb" );
String archive = meta.exportResources( transMeta, name, files, prop, rep, ms );
// after ( portable relative path, existence pre-checked )
String dir = transMeta.getVariable( "Internal.Transformation.Filename.Directory" );
String jobPath = dir + "/run_etl.kjb";
if ( !new File( jobPath ).exists() ) {
throw new IllegalStateException( "Referenced job missing: " + jobPath );
}
meta.setSpecificationMethod( ObjectLocationSpecificationMethod.FILENAME );
meta.setFileName( jobPath );
String archive = meta.exportResources( transMeta, name, files, prop, rep, ms ); Defensive patterns
Strategy: validation
Validate before calling
JobExecutorMeta m = ...;
String jobFile = m.getFileName();
if ( ObjectLocationSpecificationMethod.FILENAME.equals( m.getSpecificationMethod() )
&& ( jobFile == null || !new File( jobFile ).canRead() ) ) {
throw new IllegalStateException( "Job Executor references unreadable job: " + jobFile );
} Type guard
boolean hasResolvableJobSpec( JobExecutorMeta m ) {
return m.getSpecificationMethod() != null &&
( ObjectLocationSpecificationMethod.FILENAME.equals( m.getSpecificationMethod() )
? new File( m.getFileName() ).canRead()
: m.getJobObjectId() != null );
} Try / catch
try {
String archive = meta.exportResources( transMeta, name, files, props, rep, ms );
} catch ( KettleException e ) {
if ( e.getMessage() != null && e.getMessage().contains( meta.getFileName() ) ) {
throw new IllegalStateException( "Fix Job Executor reference to: " + meta.getFileName(), e );
}
throw e;
} Prevention
- Prefer repository-relative or Internal.*-variable paths over absolute file paths in Job Executor steps.
- Pre-check referenced job files exist before running export/share operations.
- Keep sub-jobs in the same VCS/project directory tree as the parent transformation.
- Open each referenced sub-job in Spoon after refactors to confirm it still resolves.
When it happens
Trigger: Calling exportResources() (e.g. during job/transformation export via testExportResources) when the referenced job file does not exist at fileName, the repository JobObjectReference cannot be resolved, or the job XML/kjb is malformed and JobMeta.loadJob fails.
Common situations: Exporting a transformation that uses a Job Executor step after the sub-job file was moved/renamed; relative path resolution failing because the transformation is exported to a different directory; referencing a job stored in a repository that is not connected or has been deleted; copying transformations between environments where the referenced job path is environment-specific.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- AccessInput.Log.RequiredFilesMissing
- ChangeFileEncoding.Error.SourceFileNotExists
- Error reading DBF file
- Error retrieving command string
- file [ + ArgList[0] + ] can not be found!
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/7b26f6cfd97244a9.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/jobexecutor/JobExecutorMeta.java:748
// Set the correct filename inside the XML.
//
executorJobMeta.setFilename( newFilename );
// exports always reside in the root directory, in case we want to turn
// this into a file repository...
//
executorJobMeta.setRepositoryDirectory( new RepositoryDirectory() );
// change it in the job entry
//
fileName = newFilename;
setSpecificationMethod( ObjectLocationSpecificationMethod.FILENAME );
return proposedNewFilename;
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString(
PKG, "JobExecutorMeta.Exception.UnableToLoadJob", fileName ), e );
}
}
@Override
public StepDataInterface getStepData() {
return new JobExecutorData();
}
@Override
public StepIOMetaInterface getStepIOMeta() {
StepIOMetaInterface ioMeta = super.getStepIOMeta( false );
if ( ioMeta == null ) {
ioMeta = new StepIOMeta( true, true, true, false, true, false );
ioMeta.addStream( new Stream( StreamType.TARGET, executionResultTargetStepMeta, BaseMessages.getString(
PKG, "JobExecutorMeta.ResultStream.Description" ), StreamIcon.TARGET, null ) );View on GitHub (pinned to f3058517a1)