grpc/grpc-java · error · IOException
ProxySelector ${proxySelectorClass} returned ${nullOrEmptyLi
Error message
ProxySelector ${proxySelectorClass} returned ${nullOrEmptyList}, which violates the java.net.ProxySelector#select(URI) contract What it means
gRPC's ProxyDetectorImpl delegates proxy discovery to java.net.ProxySelector.select(URI). The JDK contract requires a non-null, non-empty result; a custom ProxySelector that returns null or an empty list violates this, and gRPC fails the detection with an IOException naming the offending implementation.
Source
Thrown at core/src/main/java/io/grpc/internal/ProxyDetectorImpl.java:213
} catch (final URISyntaxException e) {
log.log(
Level.WARNING,
"Failed to construct URI for proxy lookup, proceeding without proxy",
e);
return null;
}
ProxySelector proxySelector = this.proxySelector.get();
if (proxySelector == null) {
log.log(Level.FINE, "proxy selector is null, so continuing without proxy lookup");
return null;
}
List<Proxy> proxies = proxySelector.select(uri);
// ProxySelector.select(URI) is contractually required to return a non-null, non-empty list.
// Surface the offending implementation's class name so a broken ProxySelector can be fixed.
if (proxies == null || proxies.isEmpty()) {
throw new IOException(
"ProxySelector " + proxySelector.getClass().getName()
+ " returned " + (proxies == null ? "null" : "an empty list")
+ ", which violates the java.net.ProxySelector#select(URI) contract");
}
if (proxies.size() > 1) {
log.warning("More than 1 proxy detected, gRPC will select the first one");
}
Proxy proxy = proxies.get(0);
if (proxy.type() == Proxy.Type.DIRECT) {
return null;
}
InetSocketAddress proxyAddr = (InetSocketAddress) proxy.address();
// The prompt string should be the realm as returned by the server.
// We don't have it because we are avoiding the full handshake.
String promptString = "";
PasswordAuthentication auth =
authenticationProvider.requestPasswordAuthentication(View on GitHub (pinned to 64daddc1f3)
Solutions
- Fix the custom ProxySelector to return Proxy.NO_PROXY instead of null or an empty list when no proxy applies
- Implement select() to always return a list with at least one Proxy (Direct for no proxy)
- Handle the IOException from gRPC's proxy detection and fall back to a direct connection
- Remove/uninstall the broken ProxySelector (ProxySelector.setDefault) and rely on standard -Dhttps.proxyHost settings
Example fix
// before
public List<Proxy> select(URI uri) {
if (!"https".equals(uri.getScheme())) return null;
...
}
// after
public List<Proxy> select(URI uri) {
if (!"https".equals(uri.getScheme())) return Collections.singletonList(Proxy.NO_PROXY);
...
} Defensive patterns
Strategy: try-catch
Validate before calling
ProxySelector sel = ProxySelector.getDefault();
List<Proxy> proxies = sel.select(uri);
if (proxies == null || proxies.isEmpty()) {
// broken selector; restore default or fix before starting gRPC channels
} Try / catch
try { channel = builder.build(); } catch (IOException e) { if (e.getMessage().contains("violates the java.net.ProxySelector#select(URI) contract")) { ProxySelector.setDefault(null); /* or fix selector */ } else throw e; } Prevention
- Custom ProxySelectors must return Proxy.NO_PROXY, never null or empty lists
- Test your ProxySelector with all URI schemes your app dials
- Prefer standard -Dhttps.proxyHost configuration over custom selectors
When it happens
Trigger: System properties java.net.useSystemProxies or -Dhttp(s).proxyHost with a custom/3rd-party ProxySelector installed via ProxySelector.setDefault that returns null or empty for the gRPC target URI.
Common situations: Corporate environment with a broken custom ProxySelector; custom selector not handling the grpc scheme/URI, returning null instead of Proxy.NO_PROXY (empty list also violates contract; must return Proxy.NO_PROXY for direct).
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
- closed
- \n not found: ${hex}
- Received an unexpected response from a host at the S2A's add
- Fail to read bootstrap file
- No ALTS context information found
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/21633ee56d4b3ea0.
Report an issue: GitHub.