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

  1. Fix the custom ProxySelector to return Proxy.NO_PROXY instead of null or an empty list when no proxy applies
  2. Implement select() to always return a list with at least one Proxy (Direct for no proxy)
  3. Handle the IOException from gRPC's proxy detection and fall back to a direct connection
  4. 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

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


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/21633ee56d4b3ea0. Report an issue: GitHub.