flowable/flowable-engine · error · FlowableIllegalArgumentException

Delegate expression " + expression + " did not resolve to an

Error message

Delegate expression " + expression + " did not resolve to an implementation of " + HttpResponseHandler.class

What it means

Thrown as FlowableIllegalArgumentException when a delegate expression configured for an HTTP response handler resolves to an object that does not implement org.flowable.http.HttpResponseHandler. During response handling Flowable evaluates the delegate expression and requires the result to be an HttpResponseHandler so it can be wrapped in HttpResponseHandlerInvocation. Same contract as the request-side check but for responses.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/http/handler/DelegateExpressionHttpHandler.java:62

    @Override
    public void handleHttpRequest(VariableContainer execution, HttpRequest httpRequest, FlowableHttpClient client) {
        Object delegate = DelegateExpressionUtil.resolveDelegateExpression(expression, execution, fieldDeclarations);
        if (delegate instanceof HttpRequestHandler) {
            CommandContextUtil.getProcessEngineConfiguration().getDelegateInterceptor().handleInvocation(
                            new HttpRequestHandlerInvocation((HttpRequestHandler) delegate, execution, httpRequest, client));
        } else {
            throw new FlowableIllegalArgumentException("Delegate expression " + expression + " did not resolve to an implementation of " + HttpRequestHandler.class);
        }
    }

    @Override
    public void handleHttpResponse(VariableContainer execution, HttpResponse httpResponse) {
        Object delegate = DelegateExpressionUtil.resolveDelegateExpression(expression, execution, fieldDeclarations);
        if (delegate instanceof HttpResponseHandler) {
            CommandContextUtil.getProcessEngineConfiguration().getDelegateInterceptor().handleInvocation(
                            new HttpResponseHandlerInvocation((HttpResponseHandler) delegate, execution, httpResponse));
        } else {
            throw new FlowableIllegalArgumentException("Delegate expression " + expression + " did not resolve to an implementation of " + HttpResponseHandler.class);
        }
    }

    /**
     * returns the expression text for this execution listener. Comes in handy if you want to check which listeners you already have.
     */
    public String getExpressionText() {
        return expression.getExpressionText();
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Make the class implement org.flowable.http.HttpResponseHandler (handleHttpResponse method).
  2. If one bean must handle both, implement both HttpRequestHandler and HttpResponseHandler.
  3. Verify the delegateExpression in the BPMN XML resolves to the intended response-handler bean.
  4. Add a unit test that resolves the bean and asserts `bean instanceof HttpResponseHandler` before deploying the process.

Example fix

// before
public class MyHandler implements HttpRequestHandler { ... }

// after
import org.flowable.http.*;
public class MyHandler implements HttpRequestHandler, HttpResponseHandler {
    public void handleHttpRequest(VariableContainer e, HttpRequest r, FlowableHttpClient c) { ... }
    public void handleHttpResponse(VariableContainer e, HttpResponse r) { ... }
}
Defensive patterns

Strategy: type-guard

Validate before calling

Object delegate = DelegateExpressionUtil.resolveDelegateExpression(expression, execution);
if (!(delegate instanceof HttpResponseHandler)) {
    throw new IllegalStateException("Bean for " + expression + " must implement HttpResponseHandler");
}

Type guard

boolean isValidHttpResponseDelegate(Object o) {
    return o instanceof org.flowable.http.HttpResponseHandler;
}

Try / catch

try {
    delegateHandler.handleHttpResponse(execution, response);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("did not resolve to an implementation of")) {
        logger.error("HTTP response handler delegate misconfigured: " + e.getMessage());
    } else { throw e; }
}

Prevention

When it happens

Trigger: A BPMN HTTP task defines a delegateExpression for the response handler; when the HTTP response arrives, DelegateExpressionUtil.resolveDelegateExpression returns an object that fails `instanceof HttpResponseHandler` in DelegateExpressionHttpHandler.handleHttpResponse.

Common situations: Reusing the same bean for both request and response handler when it implements only HttpRequestHandler; bean refactoring dropped the HttpResponseHandler interface; EL expression typo resolving to the wrong bean; copying config from a request-handler example.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/d1ea18761102d32b. Report an issue: GitHub.