pentaho/pentaho-kettle · error · KettleException
Repository required.
Error message
Repository required.
What it means
RunJobServlet.loadJob requires a Repository to load a job by repository path; if repository is null it throws KettleException 'Repository required.' The servlet's job-loading path was invoked without a repository context.
Solutions
- Configure a repository for the Carte server (define repositories.xml in .kettle/KETTLE_HOME with valid connection details).
- Use the file-based variant instead: runJob with a filename (input file parameter) rather than a repository path, or use RegisterPackageServlet for file uploads.
- Verify the repository connection credentials/login so the servlet can construct the Repository object rather than passing null.
- If embedding the servlet, pass a non-null Repository (e.g. KettleDatabaseRepository initialized and connected) into loadJob.
Example fix
// before // repositories.xml absent; servlet gets repository == null // after // ~/.kettle/repositories.xml with <repository><name>prod</name>... </repository>, // and request uses repository-based path: /kettle/runJob/?job=/home/admin/myjob&...
Defensive patterns
Strategy: validation
Validate before calling
import java.io.File;
boolean repositoryConfigured = new File(System.getProperty("user.home") + "/.kettle/repositories.xml").exists();
boolean useFileMode = repositoryConfigured ? false : true; // fall back to file-based runJob Try / catch
try {
String res = httpGet("/kettle/runJob/?job=/home/admin/myjob&...");
} catch (KettleException e) {
if (e.getMessage().contains("Repository required.")) {
// fall back to file-based invocation
res = httpGet("/kettle/runJob/?" + fileParams);
}
} Prevention
- Configure repositories.xml in $KETTLE_HOME/.kettle before using repository-path endpoints.
- Use the file/filename parameters for standalone Carte without a repository.
- Verify repository credentials resolve a connected Repository at servlet startup.
- Document which Carte endpoints require a repository and gate client calls accordingly.
When it happens
Trigger: GET /kettle/runJob/ where the servlet resolves the job through a Repository but the repository reference is null — the Carte server has no repository configured (repositories.xml not defined/loaded) while the request expects repository-based lookup.
Common situations: Standalone Carte without a configured repository but calling runJob with a repository-style path; repositories.xml missing credentials or not present in KETTLE_HOME; internal call path (jobMeta) passing null repository.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- ExecuteJobServlet.Error.JobNotFoundInDirectory
- ExecuteJobServlet.Error.UnableToFindRepository
- Unable to find repository: " + repositoryName
- Could not connect to repository: ...
- Could not execute specified in a repository since we're not…
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/4d46f340fda97378.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/www/RunJobServlet.java:327
PKG, "RunJobServlet.Error.UnableToFindJob", serverConfig.getRepositoryId() ) ) );
return;
}
response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
out.println( new WebResult( WebResult.STRING_ERROR, BaseMessages.getString(
PKG, "RunJobServlet.Error.UnexpectedError", Const.CR + Const.getStackTracker( ex ) ) ) );
}
}
protected void runJob( Job job ) {
// Execute the transformation...
//
job.start();
}
private JobMeta loadJob( Repository repository, String job, 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 = job.lastIndexOf( RepositoryDirectory.DIRECTORY_SEPARATOR );
if ( lastSlash < 0 ) {
directoryPath = "/";
name = job;
} else {
directoryPath = job.substring( 0, lastSlash );
name = job.substring( lastSlash + 1 );
}
RepositoryDirectoryInterface directory =View on GitHub (pinned to f3058517a1)