pentaho/pentaho-kettle · error · HttpException
Unable to get authorization token
Error message
Unable to get authorization token <statusLine>
What it means
The job entry's OAuth2 token retrieval (used when authentication type is OAuth) POSTs credentials to the configured token URL. If the HTTP response status is not 200 OK, it throws HttpException 'Unable to get authorization token <statusLine>'. This means the identity provider refused or failed the token exchange before any mail could be fetched.
Solutions
- Read the status line in the message (e.g. 400/401) and check the IdP/token-endpoint logs for the error body; fix the offending credential or request parameter.
- Verify the token URL, client id, client secret, and redirect_uri in the job entry match the OAuth app registration exactly.
- Regenerate or refresh the expired credential/refresh token and re-enter it in the job entry.
- Confirm network/proxy access to the token endpoint (test with curl -v against the token URL).
Example fix
// before: wrong endpoint POST https://login.example.com/token -> 404 // after: correct tenant endpoint POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token -> 200
Defensive patterns
Strategy: try-catch
Validate before calling
int status = probeTokenEndpoint(tokenUrl); // pre-flight HEAD/POST check
if (status != 200) { logError("Token endpoint not healthy, HTTP " + status); return; } Try / catch
try { executeJobEntry(); } catch (RuntimeException e) {
if (e.getCause() instanceof HttpException && e.getMessage().contains("authorization token")) {
logError("OAuth token exchange failed: " + e.getCause().getMessage() + " — check client id/secret, redirect_uri, token URL");
} else { throw e; }
} Prevention
- Rotate client secrets on schedule and update the job entry before expiry.
- Match redirect_uri exactly to the OAuth app registration.
- Monitor the token endpoint from the runtime network (proxy/firewall allowlists).
When it happens
Trigger: getOauthToken(tokenUrl) executes the POST and response.getStatusLine().getStatusCode() != 200 — bad client id/secret, expired or revoked refresh token, wrong redirect_uri, wrong token endpoint URL, or the IdP returning 400/401/403/5xx.
Common situations: Expired OAuth client secret; redirect URI mismatch with the registered app; token URL typo or pointing to the wrong tenant; IdP outage returning 500/503; clock skew invalidating the grant; scopes not approved for the account.
Related errors
- CmsTokenProvider: Keycloak token request failed — HTTP
- Unable to get authorization token
- Unable to get authorization token " +…
- Auth error
- Carte.Error.NoServerFound
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/16908388b95a3b72.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/email-messages/impl/src/main/java/org/pentaho/di/job/entries/getpop/JobEntryGetPOP.java:1535
HttpPost httpPost = new HttpPost( parentJobMeta.environmentSubstitute( tokenUrl ) );
List<NameValuePair> form = new ArrayList<>();
form.add( new BasicNameValuePair( "scope", parentJobMeta.environmentSubstitute( getScope() ) ) );
form.add( new BasicNameValuePair( "client_id", parentJobMeta.environmentSubstitute( getClientId() ) ));
form.add( new BasicNameValuePair( "client_secret", parentJobMeta.environmentSubstitute( getSecretKey() ) ));
String realGrantType = parentJobMeta.environmentSubstitute( getGrant_type() );
form.add( new BasicNameValuePair( "grant_type", realGrantType ) );
if ( realGrantType.equals( JobEntryGetPOP.GRANTTYPE_REFRESH_TOKEN ) ) {
form.add( new BasicNameValuePair( JobEntryGetPOP.GRANTTYPE_REFRESH_TOKEN, parentJobMeta.environmentSubstitute( getRefresh_token() ) ) );
}
if ( realGrantType.equals( JobEntryGetPOP.GRANTTYPE_AUTHORIZATION_CODE ) ) {
form.add( new BasicNameValuePair( "code", parentJobMeta.environmentSubstitute( getAuthorization_code() ) ) );
form.add( new BasicNameValuePair( "redirect_uri", parentJobMeta.environmentSubstitute( getRedirectUri() ) ) );
}
UrlEncodedFormEntity entity = new UrlEncodedFormEntity( form, Consts.UTF_8 );
httpPost.setEntity( entity );
try ( CloseableHttpResponse response = client.execute( httpPost ) ) {
if ( response.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {
throw new HttpException( "Unable to get authorization token " + response.getStatusLine().toString() );
}
String responseBody = EntityUtils.toString( response.getEntity() );
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue( responseBody, EmailAuthenticationResponse.class );
} catch ( HttpException | IOException e ) {
throw new RuntimeException( e );
}
} catch ( IOException e ) {
throw new RuntimeException( e );
}
}
@Override
public List<ResourceReference> getResourceDependencies( JobMeta jobMeta ) {
List<ResourceReference> references = super.getResourceDependencies( jobMeta );
if ( !Utils.isEmpty( serverName ) ) {
String realServername = jobMeta.environmentSubstitute( serverName );
ResourceReference reference = new ResourceReference( this );View on GitHub (pinned to f3058517a1)