grpc/grpc-java · error · VerifyException
key ' ' missing in
Error message
key '%s' missing in '%s'
What it means
Each service-config choice from DNS must contain the `serviceConfig` key. In maybeChooseServiceConfig, after selecting a choice map, if the `serviceConfig` key is absent, the resolver throws a VerifyException describing which choice failed - the selection cannot produce a usable service config.
Solutions
- Publish the choice as an object containing a non-null `serviceConfig` key, e.g. {"clientLanguage":..., "serviceConfig":{...}}.
- Validate DNS TXT service-config choices against the gRPC service-config-choice schema before publishing.
- Remove malformed choices so the resolver can pick a valid one.
Example fix
// before (TXT record)
grpc_config=[{"clientLanguage":"java"}]
// after (TXT record)
grpc_config=[{"clientLanguage":"java","serviceConfig":{...}}] Defensive patterns
Strategy: validation
Validate before calling
Map<String, ?> choice = JsonUtil.getObject(raw, ...);
if (choice == null || !choice.containsKey("serviceConfig")) {
throw new IllegalArgumentException("service config choice lacks 'serviceConfig' key");
} Try / catch
try {
sc = maybeChooseServiceConfig(choice);
} catch (VerifyException e) {
// skip malformed choice, use default service config
} Prevention
- Validate published service-config choices against the gRPC schema.
- Include a non-null serviceConfig key in every choice object.
- Test DNS resolution against the published records in CI.
When it happens
Trigger: A DNS TXT `grpc_config` choice object that lacks the `serviceConfig` key (or has it misspelled / null), so JsonUtil.getObject returns null during service-config selection.
Common situations: Wrong service-config schema published in DNS (older or hand-written choices); fields renamed after a spec change; partial records produced by automation that failed mid-write.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- wrong type
- Address is not an IP
- Can not convert status code
- IP address can not be found: " + ex
- JNDI is not currently available
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/291bf7b17f00c4b7.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/io/grpc/internal/DnsNameResolver.java:512
}
}
List<String> clientHostnames = getHostnamesFromChoice(choice);
if (clientHostnames != null && !clientHostnames.isEmpty()) {
boolean hostnamePresent = false;
for (String clientHostname : clientHostnames) {
if (clientHostname.equals(hostname)) {
hostnamePresent = true;
break;
}
}
if (!hostnamePresent) {
return null;
}
}
Map<String, ?> sc =
JsonUtil.getObject(choice, SERVICE_CONFIG_CHOICE_SERVICE_CONFIG_KEY);
if (sc == null) {
throw new VerifyException(String.format(
"key '%s' missing in '%s'", choice, SERVICE_CONFIG_CHOICE_SERVICE_CONFIG_KEY));
}
return sc;
}
/**
* Describes a parsed SRV record.
*/
@VisibleForTesting
public static final class SrvRecord {
public final String host;
public final int port;
public SrvRecord(String host, int port) {
this.host = host;
this.port = port;
}
View on GitHub (pinned to 64daddc1f3)