grpc/grpc-java · critical · XdsInitializationException
Invalid bootstrap: 'xds_servers' does not exist.
Error message
Invalid bootstrap: 'xds_servers' does not exist.
What it means
During bootstrap parsing, BootstrapperImpl.bootstrapBuilder() requires a top-level 'xds_servers' array in the bootstrap configuration. If JsonUtil.getList(rawData, "xds_servers") returns null, the configuration is rejected with XdsInitializationException because the client has no control-plane servers to connect to.
Source
Thrown at xds/src/main/java/io/grpc/xds/client/BootstrapperImpl.java:121
throw new XdsInitializationException("Failed to parse JSON", e);
}
logger.log(XdsLogLevel.DEBUG, "Bootstrap configuration:\n{0}", rawBootstrap);
return bootstrap(rawBootstrap);
}
@Override
public BootstrapInfo bootstrap(Map<String, ?> rawData) throws XdsInitializationException {
return bootstrapBuilder(rawData).build();
}
protected BootstrapInfo.Builder bootstrapBuilder(Map<String, ?> rawData)
throws XdsInitializationException {
BootstrapInfo.Builder builder = BootstrapInfo.builder();
List<?> rawServerConfigs = JsonUtil.getList(rawData, "xds_servers");
if (rawServerConfigs == null) {
throw new XdsInitializationException("Invalid bootstrap: 'xds_servers' does not exist.");
}
List<ServerInfo> servers = parseServerInfos(rawServerConfigs, logger);
if (servers.size() > 1 && !enableXdsFallback) {
servers = ImmutableList.of(servers.get(0));
}
builder.servers(servers);
Node.Builder nodeBuilder = Node.newBuilder();
Map<String, ?> rawNode = JsonUtil.getObject(rawData, "node");
if (rawNode != null) {
String id = JsonUtil.getString(rawNode, "id");
if (id != null) {
logger.log(XdsLogLevel.INFO, "Node id: {0}", id);
nodeBuilder.setId(id);
}
String cluster = JsonUtil.getString(rawNode, "cluster");
if (cluster != null) {
logger.log(XdsLogLevel.INFO, "Node cluster: {0}", cluster);View on GitHub (pinned to 64daddc1f3)
Solutions
- Add a top-level "xds_servers" array to the bootstrap JSON with at least one server object containing "server_uri" and "channel_creds".
- Fix the key spelling — it must be exactly "xds_servers".
- Validate the file against the gRPC xDS bootstrap v3 JSON schema before deploying.
- Regenerate the bootstrap file using your mesh's official bootstrap generation tool.
Example fix
// before
{ "node": { "id": "backend" } }
// after
{
"xds_servers": [{ "server_uri": "dns:///xds.example.com:443",
"channel_creds": [{"type": "insecure"}] }]
} Defensive patterns
Strategy: validation
Validate before calling
java.util.Map<String, ?> cfg = parseBootstrapJson();
if (!(cfg.get("xds_servers") instanceof java.util.List) ||
((java.util.List<?>) cfg.get("xds_servers")).isEmpty()) {
throw new IllegalStateException("bootstrap missing non-empty 'xds_servers' list");
} Type guard
boolean hasXdsServers(java.util.Map<String, ?> cfg) {
return cfg.get("xds_servers") instanceof java.util.List
&& !((java.util.List<?>) cfg.get("xds_servers")).isEmpty();
} Prevention
- Validate bootstrap files against the gRPC xDS bootstrap v3 schema in CI.
- Use exact key names from the spec: "xds_servers", "server_uri", "channel_creds".
- Prefer generated bootstrap files from your mesh tooling over hand-written ones.
When it happens
Trigger: Bootstrap JSON lacking the 'xds_servers' key entirely, misspelling it (e.g. 'xdsServers', 'xds_server'), or providing a non-list value for it; empty JSON object {} as the bootstrap config.
Common situations: Following an outdated or wrong-version bootstrap spec (pre-xDS bootstrap v2/v3 examples); hand-writing minimal bootstrap files; tools that emit ADS config under a different key.
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
- client_listener_resource_name_template: '${clientListnerTemp
- Invalid bootstrap: missing 'server_uri'
- Invalid bootstrap: '${fieldName}' does not exist.
- unsupported ExtAuthz service type: only grpc_service is supp
- Invalid ring hash function: " + ringHash.getHashFunction()
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/2be4c0ded3f43290.
Report an issue: GitHub.