grpc/grpc-java · error · IllegalArgumentException

Has authority -- Non-empty path must start with '/'

Error message

Has authority -- Non-empty path must start with '/'

What it means

Uri's constructor validates RFC 3986 path/authority relationships. When the URI has an authority component, any non-empty path must start with '/'. Otherwise an IllegalArgumentException is thrown. This guards the invariant that hierarchical paths after an authority are root-relative.

Source

Thrown at api/src/main/java/io/grpc/Uri.java:185

  @Nullable private final String host;
  @Nullable private final String port;
  private final String path; // In RFC 3986, path is always defined (but can be empty).
  @Nullable private final String query;
  @Nullable private final String fragment;

  private Uri(Builder builder) {
    this.scheme = checkNotNull(builder.scheme, "scheme");
    this.userInfo = builder.userInfo;
    this.host = builder.host;
    this.port = builder.port;
    this.path = builder.path;
    this.query = builder.query;
    this.fragment = builder.fragment;

    // Checks common to the parse() and Builder code paths.
    if (hasAuthority()) {
      if (!path.isEmpty() && !path.startsWith("/")) {
        throw new IllegalArgumentException("Has authority -- Non-empty path must start with '/'");
      }
    } else {
      if (path.startsWith("//")) {
        throw new IllegalArgumentException("No authority -- Path cannot start with '//'");
      }
    }
  }

  /**
   * Parses a URI from its string form.
   *
   * @throws URISyntaxException if 's' is not a valid RFC 3986 URI.
   */
  public static Uri parse(String s) throws URISyntaxException {
    try {
      return create(s);
    } catch (IllegalArgumentException e) {
      throw new URISyntaxException(s, e.getMessage());

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Prefix the path with '/' when an authority is present and the path is non-empty
  2. If no path is desired, pass the empty string instead of a slash-less segment
  3. Recheck how the URI string is split into authority and path; use Uri.parse() rather than manual string slicing

Example fix

// before
Uri.newBuilder().setScheme("https").setHost("example.com").setPath("api") // throws
// after
Uri.newBuilder().setScheme("https").setHost("example.com").setPath("/api").build();
Defensive patterns

Strategy: validation

Validate before calling

if (hasAuthority && !path.isEmpty() && !path.startsWith("/")) path = "/" + path;

Try / catch

try {
  uri = builder.build();
} catch (IllegalArgumentException e) {
  throw new IllegalArgumentException("Malformed URI: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Building a Uri with setAuthority(...) and then setPath("foo") (no leading slash), or parsing a string like "scheme://hostfoo" where the path portion is non-empty and lacks a leading '/'.

Common situations: Hand-assembling target/authority strings for gRPC channels (e.g. authority "host:8080" plus a path missing its slash); mis-parsing URIs where the authority and path were split incorrectly; constructing links from concatenated strings.

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 grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/1bd2e302b492c73f. Report an issue: GitHub.