pentaho/pentaho-kettle · error · RepositoryClientException
status:
Error message
status:
What it means
RepositoryClient.throwOnError reads the HTTP error body from a Pentaho repository REST response and wraps it in a RepositoryClientException containing the raw body plus the status code (e.g. '... status:404'). It is thrown whenever the repo-vfs web-service client receives a non-success HTTP response on writeData, moveTo, rename, or getFileInfo. It signals that the server rejected the repository operation at the HTTP level.
Solutions
- Read the status code and body in the exception message and address the underlying HTTP cause (401 => re-authenticate/reconnect the repository; 404 => refresh the VFS cache and re-check file existence)
- Reconnect to the repository if the status indicates an expired session (401/403) and retry the operation
- Check whether another client moved/deleted the target file; refresh the file object before retrying
- Verify repository base URL and network/proxy configuration if the body is empty or unparseable
Example fix
// before
client.getFileInfo( path ); // may throw RepositoryClientException '... status:404'
// after
try {
client.getFileInfo( path );
} catch ( RepositoryClientException e ) {
if ( e.getMessage() != null && e.getMessage().endsWith( "status:404" ) ) {
fileObject.refresh(); // re-check existence before proceeding
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// before the call
if ( !fileObject.exists() ) { fileObject.refresh(); if ( !fileObject.exists() ) return; }
if ( repository == null || !repository.isConnected() ) { reconnectRepository(); } Type guard
boolean isHttpStatusFailure( RepositoryClientException e ) {
String m = e.getMessage();
return m != null && m.matches( ".* status:\\d{3}$" );
} Try / catch
try {
client.writeData( name, data );
} catch ( RepositoryClientException e ) {
if ( e.getMessage() != null && e.getMessage().endsWith( "status:401" ) ) {
reconnectAndRetry();
} else {
throw e;
}
} Prevention
- Check repository connectivity before long operation batches
- Refresh FileObjects before write/move operations in long-lived sessions
- Handle 401/403 statuses by re-authenticating instead of surfacing raw errors
- Avoid concurrent modification of the same repository files from multiple clients
When it happens
Trigger: Calling writeData, moveTo, rename, or getFileInfo via RepositoryClient when the server returns a non-2xx status (401 unauthenticated, 404 file not found, 409 conflict, 500 server error). Common when the repository path was deleted or renamed by another client between calls, or when the session cookie expired.
Common situations: Expired JCR session mid-operation; two Spoon instances editing the same file causing 409 on moveTo/rename; proxy or firewall returning HTML error pages that fail readEntity and yield 'Unable to get error response entity'; wrong repository base URL.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Append file in repository is not possible
- Error initialize repo:// VFS
- Invalid repository type
- No repository
- Random access to file in repository is not possible
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/22e600d4523e5f4d.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/repo-vfs/repo-vfs-ws/src/main/java/org/pentaho/di/plugins/repovfs/ws/repo/RepositoryClient.java:289
return ":" + Stream.of( path ).map( Encode::forUriComponent ).collect( Collectors.joining( ":" ) );
}
private void throwOnError( final Response response ) throws RepositoryClientException {
final int status = response.getStatus();
if ( status != HttpStatus.SC_OK ) {
if ( status == HttpStatus.SC_MOVED_TEMPORARILY
|| status == HttpStatus.SC_FORBIDDEN
|| status == HttpStatus.SC_UNAUTHORIZED ) {
throw new RepositoryClientException( "Auth error" );
} else {
String errMsg;
try {
errMsg = response.readEntity( String.class );
} catch ( Exception e ) {
errMsg = "Unable to get error response entity";
}
throw new RepositoryClientException( errMsg + " status:" + status );
}
}
}
private static String encodePath( String path ) {
String repoEncoded = RepositoryPathEncoder.encodeRepositoryPath( path );
return Encode.forUriComponent( repoEncoded );
}
}
View on GitHub (pinned to f3058517a1)