pentaho/pentaho-kettle · error · KettleException

MetaInjectMeta.Exception.UnableToLoadTransformationFromFile

Error message

MetaInjectMeta.Exception.UnableToLoadTransformationFromFile

What it means

During MetaInjectMeta's loadTransformation handling (specification method FILE), the mapping transformation is instantiated from a real filename via new TransMeta(...). Any failure reading/parsing that .ktr is wrapped in a KettleException using the localized message MetaInjectMeta.Exception.UnableToLoadTransformationFromFile with the filename. The injection transformation cannot resolve its target transformation.

Solutions

  1. Verify the file exists at the resolved path by logging the substituted realFilename.
  2. Fix variable values (e.g. ${Internal.Transformation.Filename.Directory}) used in the filename.
  3. Check file read permissions for the user running PDI.
  4. Open the target .ktr in Spoon to confirm it is not corrupt.

Example fix

// before: relative path that breaks at runtime
String file = "transforms/child.ktr";
// after: anchor to the transformation's own directory
String file = "${Internal.Transformation.Filename.Directory}/child.ktr";
Defensive patterns

Strategy: validation

Validate before calling

// Resolve and check the file before triggering the load
String real = space.environmentSubstitute(injectMeta.getFileName());
File f = new File(real);
if (!f.exists() || !f.canRead()) {
  throw new IllegalStateException("Mapping transformation not readable: " + real);
}

Try / catch

try {
  loadMappingTransformation();
} catch (KettleException e) {
  logError("Could not load transformation from file " + realFilename + ": " + e.getCause(), e);
}

Prevention

When it happens

Trigger: loadTransformation/MetaInjectMeta initialization with specificationMethod=FILENAME where realFilename points to a missing, unreadable, or malformed .ktr file, or variables (tmpSpace substitution) resolve to a wrong path.

Common situations: Moved/renamed transformation files; relative paths broken because the job runs from a different working directory; missing environment variables in the substitution space; permission issues on the file.

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


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

Appendix: source

Thrown at plugins/meta-inject/impl/src/main/java/org/pentaho/di/trans/steps/metainject/MetaInjectMeta.java:562

                  String tmpFilename =
                    realFilename.substring( realFilename.lastIndexOf( "/" ) + 1, realFilename.indexOf( "."
                      + Const.STRING_TRANS_DEFAULT_EXT ) );
                  String dirStr = realFilename.substring( 0, realFilename.lastIndexOf( "/" ) );
                  RepositoryDirectoryInterface dir = rep.findDirectory( dirStr );
                  mappingTransMeta = rep.loadTransformation( tmpFilename, dir, null, true, null );
                } catch ( KettleException ke2 ) {
                  // fall back to try loading from file system (transMeta is going to be null)
                }
              }
            }
          }
          if ( mappingTransMeta == null ) {
            mappingTransMeta = new TransMeta( bowl, realFilename, metaStore, rep, false, tmpSpace, null );
            mappingTransMeta.getLogChannel().logDetailed( "Loading Mapping from repository",
              "Mapping transformation was loaded from XML file [" + realFilename + "]" );
          }
        } catch ( Exception e ) {
          throw new KettleException( BaseMessages.getString( PKG,
            "MetaInjectMeta.Exception.UnableToLoadTransformationFromFile", realFilename ), e );
        }
        break;

      case REPOSITORY_BY_NAME:
        String realTransname = tmpSpace.environmentSubstitute( injectMeta.getTransName() );
        String realDirectory = tmpSpace.environmentSubstitute( injectMeta.getDirectoryPath() );
        if ( rep != null ) {
          if ( !Utils.isEmpty( realTransname ) && !Utils.isEmpty( realDirectory ) && rep != null ) {
            RepositoryDirectoryInterface repdir = rep.findDirectory( realDirectory );
            if ( repdir != null ) {
              try {
                // reads the last revision in the repository...
                //
                // TODO: FIXME: see if we need to pass external MetaStore references to the repository?
                //
                mappingTransMeta = rep.loadTransformation( realTransname, repdir, null, true, null );

View on GitHub (pinned to f3058517a1)