flowable/flowable-engine · error · FlowableException

Invalid URL exception occurred

Error message

Invalid URL exception occurred

What it means

prepareRequest builds a java.net.URI from the request info; if the URL string is malformed, URISyntaxException is thrown and re-wrapped as this FlowableException. The library throws it because Spring WebClient requires a syntactically valid URI before any request can be prepared.

Solutions

  1. Fix the URL string so it is a valid absolute URI (include scheme, encode path/query with URLEncoder or UriComponentsBuilder).
  2. Validate the URL at configuration time using 'new URI(url)' in a try block before wiring it into the HTTP task.
  3. If the URL is dynamic, sanitize/encode variable values before they reach the request info.

Example fix

// before
requestInfo.setUrl(base + "/search?q=" + term);

// after
requestInfo.setUrl(base + "/search?q=" + URLEncoder.encode(term, StandardCharsets.UTF_8));
Defensive patterns

Strategy: validation

Validate before calling

try {
    new java.net.URI(url);
} catch (java.net.URISyntaxException e) {
    throw new IllegalArgumentException("Invalid HTTP task URL: " + url, e);
}
if (!url.startsWith("http://") && !url.startsWith("https://")) {
    throw new IllegalArgumentException("URL must be absolute http(s): " + url);
}

Try / catch

try {
    client.prepareRequest(requestInfo);
} catch (FlowableException e) {
    if (e.getMessage().contains("Invalid URL")) {
        logger.error("Bad URL configured: {}", requestInfo.getUrl(), e.getCause());
    }
}

Prevention

When it happens

Trigger: Setting a request URL containing illegal characters (spaces, unencoded braces, non-ASCII chars), a missing scheme (e.g. 'example.com/api' instead of 'https://example.com/api'), or interpolating a null/empty host from a process variable.

Common situations: HTTP task URL assembled from process variables with unencoded query values; missing 'https://' prefix in config; copy-pasted URL with spaces; special characters like '|' or '{' in query parameters.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-http-common/src/main/java/org/flowable/http/common/impl/spring/reactive/SpringWebClientFlowableHttpClient.java:171

                case "HEAD": {
                    headersSpec = webClient.head().uri(uri);
                    break;
                }
                case "OPTIONS": {
                    headersSpec = webClient.options().uri(uri);
                    break;
                }
                default: {
                    throw new FlowableException(requestInfo.getMethod() + " HTTP method not supported");
                }
            }

            setHeaders(headersSpec, requestInfo.getHttpHeaders());
            setHeaders(headersSpec, requestInfo.getSecureHttpHeaders());

            return new WebClientExecutableHttpRequest(headersSpec, !requestInfo.isNoRedirects());
        } catch (URISyntaxException ex) {
            throw new FlowableException("Invalid URL exception occurred", ex);
        }
    }

    public static boolean shouldFollowRedirect(HttpClientRequest request, HttpClientResponse response) {
        boolean followRedirect = request.currentContextView().getOrDefault(FOLLOW_REDIRECT_CONTEXT_KEY, Boolean.FALSE);
        int statusCode = response.status().code();
        return followRedirect && statusCode >= 300 && statusCode < 400;
    }

    protected WebClient determineWebClient(HttpRequest requestInfo) {
        if (requestInfo.getTimeout() <= 0) {
            return webClient;
        }

        Duration requestTimeout = Duration.ofMillis(requestInfo.getTimeout());
        if (requestTimeout.equals(initialRequestTimeout)) {
            // If the request timeout is the same as the initial request timeout then there is nothing to do
            return webClient;

View on GitHub (pinned to d6d39ce1c6)