pentaho/pentaho-kettle · error · KettleException
Rest.Error.CanNotReadURL
Rest.Error.CanNotReadURL
Error message
Rest.Error.CanNotReadURL
What it means
Rest.callRest wraps the whole REST invocation (client creation, request build, execution) and converts any exception into a KettleException with the localized message Rest.Error.CanNotReadURL, including the resolved URL (data.realUrl). It is the generic 'the REST call did not succeed' boundary for this Pentaho Kettle step.
Solutions
- Read the chained cause exception (getCause()) to find the real failure (UnknownHostException, ConnectException, SSLHandshakeException, etc.)
- Verify the URL configured in the step (or in the URL input field for the current row) is correct and reachable (curl it)
- Check hostname resolution and firewall/proxy settings on the machine running the transformation
- If the URL comes from a field, preview the row data to confirm the value is a valid URL
- Test SSL configuration (trust store, 'ignore SSL' option) if the cause is a handshake failure
Example fix
// before
data.realUrl = urlInField ? row[urlFieldIdx] : meta.getUrl();
// after
String candidate = urlInField ? row[urlFieldIdx] : meta.getUrl();
if ( candidate == null || !candidate.matches( "^https?://.+" ) ) {
throw new KettleException( "Invalid REST URL: " + candidate );
}
data.realUrl = candidate; Defensive patterns
Strategy: try-catch
Validate before calling
String url = meta.isUrlInField() ? (String) rowData[data.indexOfUrlField] : environmentSubstitute( meta.getUrl() );
if ( url == null || !url.matches( "^https?://[^\s]+$" ) ) {
throw new KettleException( "Invalid REST URL: " + url );
} Try / catch
try {
Object[] out = step.callRest( row );
} catch ( KettleException e ) {
Throwable cause = e.getCause();
if ( cause instanceof java.net.UnknownHostException ) { /* fix DNS */ }
else if ( cause instanceof javax.net.ssl.SSLException ) { /* fix trust store */ }
else if ( cause instanceof java.net.ConnectException ) { /* service down */ }
log.error( "REST call to " + realUrl + " failed", e );
} Prevention
- Preview row data when URL-in-field is enabled to catch bad values before run time
- Always read the cause chain — CanNotReadURL is only a wrapper
- Validate URL fields with a regex or a Filter step upstream
- Test connectivity (curl/telnet) from the machine running the transformation
When it happens
Trigger: Any failure inside callRest: malformed URL, unknown host, connection refused, invalid method field, SSL errors, or a runtime failure while building/executing the request against data.realUrl.
Common situations: Typo or missing protocol in the URL field; DNS failure in an air-gapped environment; target service down; URL taken from an input field containing bad data at runtime.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- HTTP.Error.UnknownHostException
- HTTP.Exception.IllegalStatusCode
- HTTP.Log.UnableGetResult
- HTTPPOST.Exception.IllegalStatusCode
- Request could not be processed
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/865395867b452375.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/rest/core/src/main/java/org/pentaho/di/trans/steps/rest/Rest.java:83
*/
public class Rest extends BaseStep implements StepInterface {
private static Class<?> PKG = RestMeta.class; // for i18n purposes, needed by Translator2!!
private static final String HEADER_CONTENT_TYPE = "Content-Type";
private RestMeta meta;
private RestData data;
public Rest( StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta, Trans trans ) {
super( stepMeta, stepDataInterface, copyNr, transMeta, trans );
}
protected Object[] callRest( Object[] rowData ) throws KettleException {
try ( Client client = getClient( rowData ) ) {
WebTarget target = buildRequest( client, rowData );
return invokeRequest( target, rowData );
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString( PKG, "Rest.Error.CanNotReadURL", data.realUrl ), e );
}
}
protected Client getClient( Object[] rowData ) throws KettleException {
// get dynamic url ?
if ( meta.isUrlInField() ) {
data.realUrl = data.inputRowMeta.getString( rowData, data.indexOfUrlField );
}
// get dynamic method?
if ( meta.isDynamicMethod() ) {
data.method = data.inputRowMeta.getString( rowData, data.indexOfMethod );
if ( Utils.isEmpty( data.method ) ) {
throw new KettleException( BaseMessages.getString( PKG, "Rest.Error.MethodMissing" ) );
}
}
if ( isDetailed() ) {View on GitHub (pinned to f3058517a1)