grpc/grpc-java · error · IllegalArgumentException

Scheme must start with an alphabetic char

Error message

Scheme must start with an alphabetic char

What it means

Uri.Builder.setRawScheme() validates the scheme: it must be non-empty, start with an alphabetic character (RFC 3986: ALPHA *( ALPHA / DIGIT / '+' / '-' / '.' )), and contain only scheme-legal characters. An empty or non-alphabetic-initial scheme triggers IllegalArgumentException "Scheme must start with an alphabetic char"; a later invalid character produces the index-specific message.

Source

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

    }

    /**
     * Sets the scheme, e.g. "https", "dns" or "xds".
     *
     * <p>This field is required.
     *
     * @return this, for fluent building
     * @throws IllegalArgumentException if the scheme is invalid.
     */
    @CanIgnoreReturnValue
    public Builder setScheme(String scheme) {
      return setRawScheme(scheme.toLowerCase(Locale.ROOT));
    }

    @CanIgnoreReturnValue
    Builder setRawScheme(String scheme) {
      if (scheme.isEmpty() || !alphaChars.get(scheme.charAt(0))) {
        throw new IllegalArgumentException("Scheme must start with an alphabetic char");
      }
      for (int i = 0; i < scheme.length(); i++) {
        char c = scheme.charAt(i);
        if (!schemeChars.get(c)) {
          throw new IllegalArgumentException("Invalid character in scheme at index " + i);
        }
      }
      this.scheme = scheme;
      return this;
    }

    /**
     * Specifies the new URI's path component as a string of zero or more '/' delimited segments.
     *
     * <p>Path segments can consist of any string of codepoints. Codepoints that can't be encoded
     * literally will be percent-encoded for you.
     *
     * <p>If a URI contains an authority component, then the path component must either be empty or

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Ensure the scheme starts with a letter and contains only [A-Za-z0-9+.-]
  2. Trim the input and re-split at the first ':' so the scheme excludes stray characters
  3. Prefer Uri.parse()/create() over manually calling setRawScheme with split components
  4. Reject empty schemes at config-load time with a friendly error

Example fix

// before
String s = "1grpc://host";
builder.setRawScheme(s.substring(0, s.indexOf(':'))); // "1grpc" -> throws
// after
int i = s.indexOf("://");
String scheme = s.substring(0, i);
if (scheme.isEmpty() || !Character.isLetter(scheme.charAt(0))) {
  throw new IllegalArgumentException("Invalid scheme: " + scheme);
}
builder.setRawScheme(scheme.toLowerCase(Locale.ROOT));
Defensive patterns

Strategy: validation

Validate before calling

static boolean validScheme(String s) {
  if (s == null || s.isEmpty() || !Character.isLetter(s.charAt(0))) return false;
  return s.chars().allMatch(c -> Character.isLetterOrDigit(c) || c=='+' || c=='-' || c=='.');
}

Type guard

static String normalizeScheme(String s) {
  return validScheme(s) ? s.toLowerCase(Locale.ROOT) : null;
}

Try / catch

try {
  builder.setRawScheme(scheme);
} catch (IllegalArgumentException e) {
  throw new IllegalArgumentException("Invalid scheme '" + scheme + "': " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling setScheme/setRawScheme with an empty string, a scheme starting with a digit or '-'/'.' (e.g. '3dns', '-grpc'), or a scheme containing ':', '/', or other illegal characters; programmatically splitting "scheme:rest" at the wrong index so the scheme string is malformed.

Common situations: Manual URI splitting where the colon position is mis-computed (scheme includes preceding chars or is empty); config that stores the scheme separately with numeric values; normalizing schemes from user input without validation.

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/1c07de1a33b1ad4d. Report an issue: GitHub.