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
- Ensure the file's top level is a JSON object like {"trust_domains": {"domain": {"keys": [...]}}}, keyed under trust_domains
- Verify the file with: python3 -c 'import json;d=json.load(open("bundle.json"));print(type(d))' — must be dict
- 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
- Fetch bundles from the SPIRE agent bundle endpoint in native object form
- Never paste raw PEM into the .json bundle file
- Atomically re-fetch and JSON-validate the bundle before swapping it in
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
- 'kty' parameter must be one of %s but '%s' found. Certificat
- 'kid' parameter must not be set. Certificate loading for tru
- 'use' parameter must be '%s' but '%s' found. Certificate loa
- Certificate can't be parsed. Certificate loading for trust d
- Authorization policy should be a JSON object. Found: null
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/314cbb2b95af4c0a.
Report an issue: GitHub.