OpenFeign/feign · error · IOException
URL ' ' couldn't be parsed into a URI
Error message
URL '${request.url()}' couldn't be parsed into a URI What it means
ApacheHttpClient.execute converts the Feign Request URL into an HttpUriRequest; if the URL string cannot be parsed into a java.net.URI (URISyntaxException), it is rethrown as an IOException with the offending URL in the message. Feign URLs are templates that should be valid URIs, so this indicates malformed URL construction.
Solutions
- Log/inspect the URL in the message and fix the illegal character at its source.
- URL-encode path and query parameter values before passing them (or rely on Feign's @Param expansion with proper encoding).
- Fix the @RequestLine/URL template so placeholders are expanded, not left with literal braces.
- Validate the base URL/host configuration for stray whitespace, double slashes, or bad characters.
Example fix
// before
String name = "john doe";
api.getUser(name); // GET /users/john doe -> URISyntaxException
// after
String name = URLEncoder.encode("john doe", StandardCharsets.UTF_8);
api.getUser(name); // GET /users/john%20doe Defensive patterns
Strategy: validation
Validate before calling
static boolean isUriSafe(String url) {
try { new java.net.URI(url); return true; } catch (java.net.URISyntaxException e) { return false; }
}
// run before building the Feign request; encode values with URLEncoder if false Try / catch
try {
response = feignClient.call(param);
} catch (java.io.IOException e) {
if (e.getMessage() != null && e.getMessage().contains("couldn't be parsed into a URI")) {
throw new IllegalArgumentException("Bad URL built from param, encode it first", e);
}
throw e;
} Prevention
- URL-encode all path and query parameter values
- Never build URLs via raw string concatenation for Feign targets
- Trim whitespace from configured base URLs
- Avoid characters like space, '{', '}', '|' in parameter values
When it happens
Trigger: Calling a Feign client where the resolved target URL contains illegal characters (unencoded spaces, '{', '}', '|', non-ASCII characters), an empty path component bug, or a path/query parameter expanded with raw special characters not URL-encoded by the encoder.
Common situations: Passing path variables containing spaces or unencoded reserved characters; building target URLs by string concatenation instead of RequestTemplate; hosting config with a typo (double slashes, missing scheme handled upstream); migrating to ApacheHttpClient which is stricter than other clients.
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
- target values must be absolute.
- Target is not a valid URI.
- ${e.getMessage()}
- Empty targets don't have URLs
- is not a type supported by this encoder.
AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10).
Data as JSON: /api/errors/200bf7da2e0e3ff9.
Report an issue: GitHub.
Appendix: source
Thrown at httpclient/src/main/java/feign/httpclient/ApacheHttpClient.java:82
private static final String ACCEPT_HEADER_NAME = "Accept";
private final HttpClient client;
public ApacheHttpClient() {
this(HttpClientBuilder.create().build());
}
public ApacheHttpClient(HttpClient client) {
this.client = client;
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
HttpUriRequest httpUriRequest;
try {
httpUriRequest = toHttpUriRequest(request, options);
} catch (URISyntaxException e) {
throw new IOException("URL '" + request.url() + "' couldn't be parsed into a URI", e);
}
HttpResponse httpResponse = client.execute(httpUriRequest);
return toFeignResponse(httpResponse, request);
}
HttpUriRequest toHttpUriRequest(Request request, Request.Options options)
throws URISyntaxException {
RequestBuilder requestBuilder = RequestBuilder.create(request.httpMethod().name());
// per request timeouts
RequestConfig requestConfig =
(client instanceof Configurable
? RequestConfig.copy(((Configurable) client).getConfig())
: RequestConfig.custom())
.setConnectTimeout(options.connectTimeoutMillis())
.setSocketTimeout(options.readTimeoutMillis())
.setRedirectsEnabled(options.isFollowRedirects())
.build();View on GitHub (pinned to e2a1e27560)