pentaho/pentaho-kettle · error · KettleException
Rest.Error.MethodMissing
Rest.Error.MethodMissing
Error message
Rest.Error.MethodMissing
What it means
When the REST step is configured with a dynamic method (HTTP verb read from an input field), getClient reads that field and throws a KettleException with Rest.Error.MethodMissing if the value is null or empty. The step cannot execute a request without an HTTP method.
Solutions
- Fix the upstream step so every row has a non-empty method value (GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH)
- Add a Filter/Stream Lookup step to route rows with empty method values away from the REST step
- Check the step dialog's method-field selection points at the correct input column
- Default the method upstream: replace empty values with a sensible verb via 'If field value is null' / Value Mapper
Example fix
// before String method = row[methodIdx]; // may be empty // after String method = row[methodIdx] == null || row[methodIdx].isEmpty() ? "GET" : row[methodIdx];
Defensive patterns
Strategy: validation
Validate before calling
if ( meta.isDynamicMethod() ) {
String method = data.inputRowMeta.getString( rowData, data.indexOfMethod );
if ( method == null || method.trim().isEmpty() ) {
throw new KettleException( "Row has empty HTTP method in field: " + data.indexOfMethod );
}
} Try / catch
try {
Object[] out = step.callRest( row );
} catch ( KettleException e ) {
if ( e.getMessage() != null && e.getMessage().contains( "MethodMissing" ) ) {
log.error( "HTTP method field is empty for row — check upstream step", e );
}
} Prevention
- Guarantee the method column is populated for every row (use a default via Value Mapper or If-null step)
- Preview the transformation to confirm the method field index selected in the dialog is correct
- Filter out or dead-letter rows lacking a method before the REST step
- Avoid whitespace-only values — trim the field upstream
When it happens
Trigger: Transformations with 'Dynamic method' enabled where the method field in the incoming row is empty or null for a given row.
Common situations: Upstream step failed to populate the method column; rows from heterogeneous sources where some rows lack a method; user selected the wrong field index in the step dialog.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Rest.Error.UnknownMethod
- At least one slave server is required to be present in…
- ChangeFileEncoding.Error.TargetFileIsEmpty
- DynamicSQLRow.Exception.SQLFieldNameEmpty
- ERROR: There was an error opening the file, since the…
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/9264f98cb97f0b1b.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/rest/core/src/main/java/org/pentaho/di/trans/steps/rest/Rest.java:97
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() ) {
logDetailed( BaseMessages.getString( PKG, "Rest.Log.ConnectingToURL", data.realUrl ) );
}
// Register a custom StringMessageBodyWriter to solve PDI-17423
ClientBuilder clientBuilder = ClientBuilder.newBuilder();
clientBuilder.withConfig( data.config ).property( HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true );
if ( meta.isIgnoreSsl() || !Utils.isEmpty( data.trustStoreFile ) ) {
clientBuilder.sslContext( data.sslContext );
clientBuilder.hostnameVerifier( ( s1, s2 ) -> true );
}
Client client = clientBuilder.build();
if ( data.basicAuthentication != null ) {View on GitHub (pinned to f3058517a1)