{"record":{"id":"69c8c126aa88c961","repo":"pentaho/pentaho-kettle","slug":"http-exception-authentication","errorCode":"HTTP.Exception.Authentication","errorMessage":"HTTP.Exception.Authentication","messagePattern":"HTTP\\.Exception\\.Authentication","errorType":"exception","errorClass":"KettleStepException","httpStatus":401,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/http/HTTP.java","lineNumber":174,"sourceCode":"          httpResponse = httpClient.execute( target, method, localContext );\n        } else {\n          httpResponse = httpClient.execute( method, localContext );\n        }\n        // calculate the responseTime\n        long responseTime = System.currentTimeMillis() - startTime;\n        if ( log.isDetailed() ) {\n          log.logDetailed( BaseMessages.getString( PKG, \"HTTP.Log.ResponseTime\", responseTime, uri ) );\n        }\n        int statusCode = requestStatusCode( httpResponse );\n        // The status code\n        if ( isDebug() ) {\n          logDebug( BaseMessages.getString( PKG, \"HTTP.Log.ResponseStatusCode\", \"\" + statusCode ) );\n        }\n\n        String body;\n        switch ( statusCode ) {\n          case HttpURLConnection.HTTP_UNAUTHORIZED:\n            throw new KettleStepException( BaseMessages\n              .getString( PKG, \"HTTP.Exception.Authentication\", data.realUrl ) );\n          case -1:\n            throw new KettleStepException( BaseMessages\n              .getString( PKG, \"HTTP.Exception.IllegalStatusCode\", data.realUrl ) );\n          case HttpURLConnection.HTTP_NO_CONTENT:\n            body = \"\";\n            break;\n          default:\n            HttpEntity entity = httpResponse.getEntity();\n            if ( entity != null ) {\n              body = StringUtils.isEmpty( meta.getEncoding() ) ? EntityUtils.toString( entity ) : EntityUtils.toString( entity, meta.getEncoding() );\n            } else {\n              body = \"\";\n            }\n            break;\n        }\n\n        Header[] headers = searchForHeaders( httpResponse );","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/http/HTTP.java#L156-L192","documentation":"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.","triggerScenarios":"callHttpService executes the request, response statusCode == HttpURLConnection.HTTP_UNAUTHORIZED (401) — missing/expired/invalid credentials in Basic/Digest/Proxy auth settings.","commonSituations":"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.","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"],"exampleFix":"// before\nhttpClient = new HttpClient(); // no credentials\n// after\nCredentialsProvider provider = new BasicCredentialsProvider();\nprovider.setCredentials( AuthScope.ANY, new UsernamePasswordCredentials( user, pass ) );\nhttpClient.setCredentialsProvider( provider );","handlingStrategy":"try-catch","validationCode":"// preflight the credentials against the endpoint\nHttpURLConnection c = (HttpURLConnection) new URL( realUrl ).openConnection();\nc.setRequestProperty( \"Authorization\", authHeader );\nif ( c.getResponseCode() == 401 ) throw new IllegalStateException( \"Invalid credentials for \" + realUrl );","typeGuard":null,"tryCatchPattern":"try {\n  transformation.execute( arguments );\n} catch ( KettleStepException e ) {\n  if ( e.getMessage().contains( \"HTTP.Exception.Authentication\" ) ) {\n    log.error( \"401 from {} — refresh credentials or auth scheme\", realUrl );\n    credentialProvider.refresh();\n  } else { throw e; }\n}","preventionTips":["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"],"tags":["kettle","pdi","http","http-401","authentication"],"backgroundTag":"authentication-required","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}