pentaho/pentaho-kettle · error · KettleException

Repository required.

Error message

Repository required.

What it means

loadTrans in RunTransServlet throws KettleException("Repository required.") when the Repository argument is null even though a transformationName was supplied, i.e. the caller asked to load a transformation from a repository without providing one. When no repository is configured the servlet can only load transformations from a file path; a repository path/name combination demands a connected repository.

Solutions

  1. Add rep=<repositoryName>, user=<user>, pass=<password> query parameters to the runTrans URL so the servlet connects to the repository.
  2. If the transformation is a file, use the file form instead: trans=<full/path/file.ktr> with type=xml (no repository).
  3. Verify the repository is defined in ~/.kettle/repositories.xml on the Carte host so it can be found and connected.
  4. If embedding the servlet API, never call loadTrans with a null repository when transformationName is a repository path.

Example fix

// before
GET http://carte:8080/kettle/runTrans/?trans=/home/admin/etl/load.ktr&user=admin&pass=secret

// after (repository name supplied so repository != null)
GET http://carte:8080/kettle/runTrans/?trans=/home/admin/etl/load.ktr&rep=prodRepo&user=admin&pass=secret
Defensive patterns

Strategy: validation

Validate before calling

boolean usesRepo = params.get("rep") != null && params.get("user") != null && params.get("pass") != null;
boolean usesFile = params.get("trans").endsWith(".ktr") && !params.get("trans").startsWith("/") == false;
if (!usesRepo && !fileSpecifiedWithoutRepo(params)) throw new IllegalArgumentException("provide rep/user/pass or a file path");

Try / catch

try {
  String resp = callCarte("runTrans", params);
} catch (Exception e) {
  if (e.getMessage() != null && e.getMessage().contains("Repository required")) {
    throw new ConfigurationException("Add rep/user/pass query parameters or use a file-based trans path", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: GET /kettle/runTrans/?trans=/path/in/repo without rep/user/pass parameters (or with only some), so the servlet builds a null Repository and passes it to loadTrans; or programmatically calling loadTrans(null, name, vars).

Common situations: Carte REST scripts that omit the rep/user/pass query parameters; renamed repository credentials after a migration; mixing file-based and repository-based transformation references in one automation script.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/www/RunTransServlet.java:270

        String logging = KettleLogStore.getAppender().getBuffer( trans.getLogChannelId(), false ).toString();
        throw new KettleException( "Error executing Transformation: " + logging, executionException );
      }
    } catch ( Exception ex ) {
      logError( "Error occurred while executing transformation", ex );
      out.println( new WebResult( WebResult.STRING_ERROR, BaseMessages.getString(
        PKG, "RunTransServlet.Error.UnexpectedError", Const.CR + Const.getStackTracker( ex ) ) ) );
    }
  }

  //need for unit test
  Trans createTrans( TransMeta transMeta, SimpleLoggingObject servletLoggingObject ) {
    return new Trans( transMeta, servletLoggingObject );
  }

  private TransMeta loadTrans( Repository repository, String transformationName, VariableSpace parentVariableSpace ) throws KettleException {

    if ( repository == null ) {
      throw new KettleException( "Repository required." );
    } else {

      synchronized ( repository ) {
        // With a repository we need to load it from /foo/bar/Transformation
        // We need to extract the folder name from the path in front of the
        // name...
        //
        String directoryPath;
        String name;
        int lastSlash = transformationName.lastIndexOf( RepositoryDirectory.DIRECTORY_SEPARATOR );
        if ( lastSlash < 0 ) {
          directoryPath = "/";
          name = transformationName;
        } else {
          directoryPath = transformationName.substring( 0, lastSlash );
          name = transformationName.substring( lastSlash + 1 );
        }
        RepositoryDirectoryInterface directory =

View on GitHub (pinned to f3058517a1)