pentaho/pentaho-kettle · error · KettleStepException
HTTP.Exception.Authentication
HTTP.Exception.Authentication
Error message
HTTP.Exception.Authentication
What it means
When the HTTP step's HttpClient receives HTTP 401 Unauthorized from the target server, callHttpService throws this KettleStepException naming the URL. The library surfaces authentication rejection as a step failure rather than returning a row.
Solutions
- Correct the username/password (or proxy credentials) in the HTTP step dialog
- Match the auth scheme the server expects (Basic/Digest vs custom header/token)
- Test the URL with curl -u or a REST client to confirm credentials work
- For token-based APIs, refresh the token before the transformation or use a pre-auth step
- Check proxy settings — the 401 may come from the proxy, not the target
Example fix
// before httpClient = new HttpClient(); // no credentials // after CredentialsProvider provider = new BasicCredentialsProvider(); provider.setCredentials( AuthScope.ANY, new UsernamePasswordCredentials( user, pass ) ); httpClient.setCredentialsProvider( provider );
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight the credentials against the endpoint HttpURLConnection c = (HttpURLConnection) new URL( realUrl ).openConnection(); c.setRequestProperty( "Authorization", authHeader ); if ( c.getResponseCode() == 401 ) throw new IllegalStateException( "Invalid credentials for " + realUrl );
Try / catch
try {
transformation.execute( arguments );
} catch ( KettleStepException e ) {
if ( e.getMessage().contains( "HTTP.Exception.Authentication" ) ) {
log.error( "401 from {} — refresh credentials or auth scheme", realUrl );
credentialProvider.refresh();
} else { throw e; }
} Prevention
- Store credentials in Kettle environment variables or a vault, not hard-coded
- Verify the server's auth scheme (Basic/Digest/Bearer) matches the step config
- Refresh tokens before long-running transformations
- Test the endpoint with curl -v before scheduling
When it happens
Trigger: callHttpService executes the request, response statusCode == HttpURLConnection.HTTP_UNAUTHORIZED (401) — missing/expired/invalid credentials in Basic/Digest/Proxy auth settings.
Common situations: Password changed or service account locked; wrong scheme (e.g. server expects Bearer/OAuth not Basic); proxy requiring separate auth; auth realm/host misconfigured; token TTL expired during a long transformation.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- HTTPPOST.Exception.Authentication
- HTTP.Error.UnknownHostException
- HTTP.Exception.CouldnotFindField
- HTTP.Exception.IllegalStatusCode
- API coding error: please specify the conversion metadata…
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/69c8c126aa88c961.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/http/HTTP.java:174
httpResponse = httpClient.execute( target, method, localContext );
} else {
httpResponse = httpClient.execute( method, localContext );
}
// calculate the responseTime
long responseTime = System.currentTimeMillis() - startTime;
if ( log.isDetailed() ) {
log.logDetailed( BaseMessages.getString( PKG, "HTTP.Log.ResponseTime", responseTime, uri ) );
}
int statusCode = requestStatusCode( httpResponse );
// The status code
if ( isDebug() ) {
logDebug( BaseMessages.getString( PKG, "HTTP.Log.ResponseStatusCode", "" + statusCode ) );
}
String body;
switch ( statusCode ) {
case HttpURLConnection.HTTP_UNAUTHORIZED:
throw new KettleStepException( BaseMessages
.getString( PKG, "HTTP.Exception.Authentication", data.realUrl ) );
case -1:
throw new KettleStepException( BaseMessages
.getString( PKG, "HTTP.Exception.IllegalStatusCode", data.realUrl ) );
case HttpURLConnection.HTTP_NO_CONTENT:
body = "";
break;
default:
HttpEntity entity = httpResponse.getEntity();
if ( entity != null ) {
body = StringUtils.isEmpty( meta.getEncoding() ) ? EntityUtils.toString( entity ) : EntityUtils.toString( entity, meta.getEncoding() );
} else {
body = "";
}
break;
}
Header[] headers = searchForHeaders( httpResponse );View on GitHub (pinned to f3058517a1)