grpc/grpc-java · critical · XdsInitializationException

Invalid allowed_grpc_services config for ${targetUri}

Error message

Invalid allowed_grpc_services config for ${targetUri}

What it means

Thrown by GrpcBootstrapperImpl.parseImplSpecificObject when an entry in the bootstrap's allowed_grpc_services map does not resolve to a JSON object. Each key (target URI) must map to a server-config object containing at least channel_creds; if the value is missing, null, or of the wrong JSON type (e.g. a string or array), parsing fails with this error.

Source

Thrown at xds/src/main/java/io/grpc/xds/GrpcBootstrapperImpl.java:188

      }
    }
    return null;
  }

  @Override
  protected Optional<Object> parseImplSpecificObject(
      @Nullable Map<String, ?> rawAllowedGrpcServices)
      throws XdsInitializationException {
    if (rawAllowedGrpcServices == null || rawAllowedGrpcServices.isEmpty()) {
      return Optional.of(GrpcBootstrapImplConfig.create(AllowedGrpcServices.empty()));
    }

    ImmutableMap.Builder<String, AllowedGrpcService> builder =
        ImmutableMap.builder();
    for (String targetUri : rawAllowedGrpcServices.keySet()) {
      Map<String, ?> serviceConfig = JsonUtil.getObject(rawAllowedGrpcServices, targetUri);
      if (serviceConfig == null) {
        throw new XdsInitializationException(
            "Invalid allowed_grpc_services config for " + targetUri);
      }
      ConfiguredChannelCredentials configuredChannel =
          getChannelCredentials(serviceConfig, targetUri);

      Optional<CallCredentials> callCredentials = Optional.empty();
      List<?> rawCallCredsList = JsonUtil.getList(serviceConfig, "call_creds");
      if (rawCallCredsList != null && !rawCallCredsList.isEmpty()) {
        callCredentials =
            parseCallCredentials(JsonUtil.checkObjectList(rawCallCredsList), targetUri);
      }

      AllowedGrpcService.Builder b = AllowedGrpcService.builder()
          .configuredChannelCredentials(configuredChannel);
      callCredentials.ifPresent(b::callCredentials);
      builder.put(targetUri, b.build());
    }
    GrpcBootstrapImplConfig customConfig =

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Ensure every value in allowed_grpc_services is a JSON object containing channel_creds for that target URI.
  2. Re-check the bootstrap schema: allowed_grpc_services is a map of URI -> server config object, not a list of URIs.
  3. Run the bootstrap JSON through a schema validator or a working example before deploying.

Example fix

// before (bootstrap.json)
"allowed_grpc_services": {"trafficdirector.googleapis.com": "default"}
// after
"allowed_grpc_services": {"trafficdirector.googleapis.com": {"channel_creds": [{"type": "google_default"}]}}
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check allowed_grpc_services shape
Map<String, ?> services = JsonUtil.getObject(bootstrap, "allowed_grpc_services");
for (String uri : services.keySet()) {
  if (JsonUtil.getObject(services, uri) == null) {
    throw new IllegalArgumentException("allowed_grpc_services[" + uri + "] must be an object");
  }
}

Prevention

When it happens

Trigger: Bootstrap contains allowed_grpc_services where a target URI maps to a non-object value (string, list, or null) instead of an object with channel_creds, so JsonUtil.getObject returns null.

Common situations: Hand-written bootstrap with shorthand values for allowed_grpc_services; copy-paste errors merging JSON blocks; tooling that serializes the map values as strings.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/dc3c7fc7eb5d0fa5. Report an issue: GitHub.