grpc/grpc-java · error · IllegalArgumentException

SPIFFE Trust Bundle should be a JSON object. Found: ${type}

Error message

SPIFFE Trust Bundle should be a JSON object. Found: ${type}

What it means

SpiffeUtil.readTrustDomainsFromFile loads a SPIFFE trust bundle file and parses it as JSON. The top-level document must be a JSON object (map) containing trust_domains; if the parsed JSON is an array, string, number, or null, this IllegalArgumentException reports the actual Java type found.

Source

Thrown at core/src/main/java/io/grpc/internal/SpiffeUtil.java:195

      }
      Long sequenceNumber = JsonUtil.getNumberAsLong(domainNode, "spiffe_sequence");
      sequenceNumbers.put(trustDomainName, sequenceNumber == null ? -1L : sequenceNumber);
      List<Map<String, ?>> keysNode = JsonUtil.getListOfObjects(domainNode, "keys");
      if (keysNode == null || keysNode.size() == 0) {
        trustBundleMap.put(trustDomainName, Collections.emptyList());
        continue;
      }
      trustBundleMap.put(trustDomainName, extractCert(keysNode, trustDomainName));
    }
    return new SpiffeBundle(sequenceNumbers, trustBundleMap);
  }

  private static Map<String, ?> readTrustDomainsFromFile(String filePath) throws IOException {
    File file = new File(checkNotNull(filePath, "trustBundleFile"));
    String json = new String(Files.toByteArray(file), StandardCharsets.UTF_8);
    Object jsonObject = JsonParser.parse(json);
    if (!(jsonObject instanceof Map)) {
      throw new IllegalArgumentException(
          "SPIFFE Trust Bundle should be a JSON object. Found: "
              + (jsonObject == null ? null : jsonObject.getClass()));
    }
    @SuppressWarnings("unchecked")
    Map<String, ?> root = (Map<String, ?>)jsonObject;
    Map<String, ?> trustDomainsNode = JsonUtil.getObject(root, "trust_domains");
    checkNotNull(trustDomainsNode, "Mandatory trust_domains element is missing");
    checkArgument(trustDomainsNode.size() > 0, "Mandatory trust_domains element is missing");
    return trustDomainsNode;
  }

  private static void checkJwkEntry(Map<String, ?> jwkNode, String trustDomainName) {
    String kty = JsonUtil.getString(jwkNode, "kty");
    if (kty == null || !KTY_PARAMETER_VALUES.contains(kty)) {
      throw new IllegalArgumentException(
          String.format(
              "'kty' parameter must be one of %s but '%s' "
                  + "found. Certificate loading for trust domain '%s' failed.",

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Ensure the file's top level is a JSON object like {"trust_domains": {"domain": {"keys": [...]}}}, keyed under trust_domains
  2. Verify the file with: python3 -c 'import json;d=json.load(open("bundle.json"));print(type(d))' — must be dict
  3. Re-fetch the bundle from your SPIFFE workload API (SPIRE agent api/1/spiffe/bundle) in its native object form

Example fix

// before (bundle.json)
[{"kty":"RSA","n":"..."}]
// after
{"trust_domains": {"example.org": {"keys": [{"kty":"RSA","n":"..."}]}}}
Defensive patterns

Strategy: validation

Validate before calling

// Check bundle file top-level shape before loading
String json = new String(java.nio.file.Files.readAllBytes(path), StandardCharsets.UTF_8);
Object parsed = org.codehaus.jettison.json or your JsonParser.parse(json);
if (!(parsed instanceof Map)) {
  throw new IllegalStateException("Trust bundle must be a JSON object, got: "
      + (parsed == null ? "null" : parsed.getClass()));
}
if (!((Map<?, ?>) parsed).containsKey("trust_domains")) {
  throw new IllegalStateException("Trust bundle missing 'trust_domains'");
}

Try / catch

try {
  Map<String, ?> domains = trustDomainsNode(bundlePath);
} catch (IllegalArgumentException e) {
  log.error("SPIFFE trust bundle is not a JSON object: " + e.getMessage());
  throw new TrustBundleLoadException(e);
}

Prevention

When it happens

Trigger: Pointing the SPIFFE trust bundle file path at a file whose top-level JSON is not an object — e.g. a JSON array of keys, a bare PEM blob in a .json file, or an empty/garbled file — during trust bundle loading.

Common situations: Downloading the wrong endpoint payload (array of JWKs instead of the bundle object); a fetch job writing raw certificate text into the bundle path; truncated or corrupted bundle file.

Related errors


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