pentaho/pentaho-kettle · error · KettleException

Rest.Error.UnknownMethod

Rest.Error.UnknownMethod

Error message

Rest.Error.UnknownMethod

What it means

Rest.getResponse switches on data.method against the known HTTP verbs supported by RestMeta and throws this KettleException in the default branch when the method string matches none of them. The message is localized from Rest.Error.UnknownMethod with the offending method value interpolated.

Solutions

  1. Ensure the method field contains exactly one of GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH in uppercase
  2. Normalize the value upstream: trim and uppercase before the REST step (e.g. via a JavaScript/User Defined Java Expression step)
  3. Check RestMeta.HTTP_METHOD_* constants against the values your data produces
  4. Add a validation step that rejects unknown verbs before they reach the REST step

Example fix

// before
String method = row[methodIdx];
// after
String method = row[methodIdx] == null ? null : row[methodIdx].trim().toUpperCase();
Defensive patterns

Strategy: validation

Validate before calling

java.util.Set<String> allowed = java.util.Set.of( "GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH" );
String m = data.method == null ? null : data.method.trim().toUpperCase();
if ( m == null || !allowed.contains( m ) ) {
  throw new KettleException( "Unsupported HTTP method: " + data.method );
}

Try / catch

try {
  Response r = step.getResponse( target, row, contentType, entity );
} catch ( KettleException e ) {
  if ( e.getMessage().contains( "UnknownMethod" ) || ( e.getMessage().contains( data.method ) ) ) {
    log.error( "Method '" + data.method + "' not supported — use GET/POST/PUT/DELETE/HEAD/OPTIONS/PATCH", e );
  }
}

Prevention

When it happens

Trigger: Dynamic method field contains a value outside {GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH} (case differences or typos like 'get', 'POST ', 'FETCH').

Common situations: Typo in a constant/method field; lowercase verb from an API spec or upstream data; method field containing whitespace; user expected synonyms like 'GETLIST' to work.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/51b899f5e1444b28. Report an issue: GitHub.

Appendix: source

Thrown at plugins/rest/core/src/main/java/org/pentaho/di/trans/steps/rest/Rest.java:282

   * @param contentType  the content type
   * @param entityString the entity string
   * @return the response from the server
   * @throws KettleException in case the request could not be processed
   */
  private Response getResponse( Invocation.Builder invocationBuilder, String contentType, String entityString )
    throws KettleException {
    Response response;
    try {
      switch ( data.method ) {
        case RestMeta.HTTP_METHOD_GET -> response = invocationBuilder.get( Response.class );
        case RestMeta.HTTP_METHOD_POST -> response = invocationBuilder.post( getEntity( contentType, entityString ) );
        case RestMeta.HTTP_METHOD_PUT -> response = invocationBuilder.put( getEntity( contentType, entityString ) );
        case RestMeta.HTTP_METHOD_DELETE -> response = invocationBuilder.delete();
        case RestMeta.HTTP_METHOD_HEAD -> response = invocationBuilder.head();
        case RestMeta.HTTP_METHOD_OPTIONS -> response = invocationBuilder.options();
        case RestMeta.HTTP_METHOD_PATCH ->
          response = invocationBuilder.method( RestMeta.HTTP_METHOD_PATCH, getEntity( contentType, entityString ) );
        default -> throw new KettleException( BaseMessages.getString( PKG, "Rest.Error.UnknownMethod", data.method ) );
      }
    } catch ( Exception e ) {
      throw new KettleException( "Request could not be processed", e );
    }
    return response;
  }

  /**
   * Get entity for request using the given content type or the default one
   *
   * @param contentType  the content type
   * @param entityString the entity string
   * @return the request entity built using the given content type or the default media type
   */
  private Entity<?> getEntity( String contentType, String entityString ) {
    Entity<?> entity;

    if ( null != contentType ) {

View on GitHub (pinned to f3058517a1)