grpc/grpc-java · error · IllegalArgumentException
Missing required scheme.
Error message
Missing required scheme.
What it means
Uri.create() implements RFC 3986 parsing and requires every absolute URI to begin with a scheme followed by ':'. If scanning the string finds no ':' before the first '/', '?' or '#' (schemeColon < 0), it throws IllegalArgumentException "Missing required scheme." — unlike java.net.URI, grpc's Uri does not accept scheme-less URI references.
Source
Thrown at api/src/main/java/io/grpc/Uri.java:231
*/
public static Uri create(String s) {
Builder builder = new Builder();
int i = 0;
final int n = s.length();
// 3.1. Scheme: Look for a ':' before '/', '?', or '#'.
int schemeColon = -1;
for (; i < n; ++i) {
char c = s.charAt(i);
if (c == ':') {
schemeColon = i;
break;
} else if (c == '/' || c == '?' || c == '#') {
break;
}
}
if (schemeColon < 0) {
throw new IllegalArgumentException("Missing required scheme.");
}
builder.setRawScheme(s.substring(0, schemeColon));
// 3.2. Authority. Look for '//' then keep scanning until '/', '?', or '#'.
i = schemeColon + 1;
if (i + 1 < n && s.charAt(i) == '/' && s.charAt(i + 1) == '/') {
// "//" just means we have an authority. Skip over it.
i += 2;
int authorityStart = i;
for (; i < n; ++i) {
char c = s.charAt(i);
if (c == '/' || c == '?' || c == '#') {
break;
}
}
builder.setRawAuthority(s.substring(authorityStart, i));
}View on GitHub (pinned to 64daddc1f3)
Solutions
- Prepend an explicit scheme to the string (e.g. "https://" or the appropriate scheme) before parsing
- If the string is a host:port, wrap it in the desired scheme form before passing to Uri.create()
- Use Uri.parse() and catch the error to give users a clearer validation message
- Validate config values at startup to require an absolute URI
Example fix
// before
Uri.create("example.com/api"); // throws: no scheme
// after
Uri.create("https://example.com/api"); Defensive patterns
Strategy: validation
Validate before calling
if (!target.matches("[A-Za-z][A-Za-z0-9+.-]*:.*")) throw new IllegalArgumentException("Target requires a scheme: " + target); Try / catch
try {
uri = Uri.create(target);
} catch (IllegalArgumentException e) {
throw new InvalidEndpointException("Target missing scheme: " + target, e);
} Prevention
- Require absolute URIs in configuration; reject scheme-less strings at load time
- Document expected target formats (e.g. 'dns:///host:port') for users
- Provide a default scheme when the input is known to be a bare host/path
When it happens
Trigger: Passing a URI string with no scheme: "localhost:50051" without prefix is fine, but "//host/x", "host/path", or a bare target like "dns:///..." is fine too — the failing case is strings like "example.com/foo" or "#frag" where no colon appears before the first '/', '?', or '#'.
Common situations: gRPC target strings like "localhost:50051" are OK (scheme='localhost') but strings such as "my-service.my-ns:50051" typed without scheme in configs; ODBC-style or browser-style relative URLs reused as gRPC targets; stripping the scheme manually before calling create().
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 '//'
- Scheme must start with an alphabetic char
- Invalid host or port:
- Invalid character in scheme at index ${i}
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/73e06d5041e7a8b3.
Report an issue: GitHub.