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 orView on GitHub (pinned to 64daddc1f3)
Solutions
- Ensure the scheme starts with a letter and contains only [A-Za-z0-9+.-]
- Trim the input and re-split at the first ':' so the scheme excludes stray characters
- Prefer Uri.parse()/create() over manually calling setRawScheme with split components
- 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
- Validate schemes against [A-Za-z][A-Za-z0-9+.-]* before setRawScheme
- Split scheme at the first ':' only, and trim whitespace
- Lowercase schemes after validation
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
- Has authority -- Non-empty path must start with '/'
- No authority -- Path cannot start with '//'
- Missing required scheme.
- Invalid character in scheme at index ${i}
- Invalid host or port:
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/1c07de1a33b1ad4d.
Report an issue: GitHub.