grpc/grpc-java · error · NullPointerException
either 'ca_certificate_file' or 'spiffe_trust_bundle_map_fil
Error message
either 'ca_certificate_file' or 'spiffe_trust_bundle_map_file' is required in the config
What it means
FileWatcherCertificateProviderProvider.validateAndTranslateConfig validates the JSON config for the file_watcher certificate provider. When SPIFFE support is enabled, the config must supply at least one trust anchor source: a root CA certificate file ('ca_certificate_file') or a SPIFFE trust bundle map file ('spiffe_trust_bundle_map_file'). If neither key is present, a NullPointerException with this message is thrown (misleading exception type, but it signals a missing required config field).
Source
Thrown at xds/src/main/java/io/grpc/xds/internal/security/certprovider/FileWatcherCertificateProviderProvider.java:110
configObj.refrehInterval,
scheduledExecutorServiceFactory.create(),
timeProvider);
}
private static String checkForNullAndGet(Map<String, ?> map, String key) {
return checkNotNull(JsonUtil.getString(map, key), "'" + key + "' is required in the config");
}
private static Config validateAndTranslateConfig(Object config) {
checkArgument(config instanceof Map, "Only Map supported for config");
@SuppressWarnings("unchecked") Map<String, ?> map = (Map<String, ?>)config;
Config configObj = new Config();
configObj.certFile = checkForNullAndGet(map, CERT_FILE_KEY);
configObj.keyFile = checkForNullAndGet(map, KEY_FILE_KEY);
if (enableSpiffe) {
if (!map.containsKey(ROOT_FILE_KEY) && !map.containsKey(SPIFFE_TRUST_MAP_FILE_KEY)) {
throw new NullPointerException(
String.format("either '%s' or '%s' is required in the config",
ROOT_FILE_KEY, SPIFFE_TRUST_MAP_FILE_KEY));
}
if (map.containsKey(SPIFFE_TRUST_MAP_FILE_KEY)) {
configObj.spiffeTrustMapFile = JsonUtil.getString(map, SPIFFE_TRUST_MAP_FILE_KEY);
} else {
configObj.rootFile = JsonUtil.getString(map, ROOT_FILE_KEY);
}
} else {
configObj.rootFile = checkForNullAndGet(map, ROOT_FILE_KEY);
}
String refreshIntervalString = JsonUtil.getString(map, REFRESH_INTERVAL_KEY);
if (refreshIntervalString != null) {
try {
Duration duration = Durations.parse(refreshIntervalString);
configObj.refrehInterval = duration.getSeconds();
checkArgument(configObj.refrehInterval > 0L, "refreshInterval needs to be greater than 0");
} catch (ParseException e) {View on GitHub (pinned to 64daddc1f3)
Solutions
- Add 'ca_certificate_file': '<path to root CA pem>' to the file_watcher provider config
- Alternatively add 'spiffe_trust_bundle_map_file': '<path to trust bundle JSON>' for SPIFFE trust domains
- Verify the bootstrap certProviders JSON contains one of the two keys when SPIFFE is enabled
- Fix the control plane or deployment templates that generate the provider config to always include a trust anchor
Example fix
// before
{"certificate_file": "cert.pem", "private_key_file": "key.pem"}
// after
{"certificate_file": "cert.pem", "private_key_file": "key.pem", "ca_certificate_file": "ca.pem"} Defensive patterns
Strategy: validation
Validate before calling
// Validate file_watcher provider config JSON before registration
boolean validTrustSource(Map<String, ?> map) {
return map.containsKey("ca_certificate_file") || map.containsKey("spiffe_trust_bundle_map_file");
}
if (!validTrustSource(config)) throw new IllegalArgumentException("file_watcher config needs ca_certificate_file or spiffe_trust_bundle_map_file"); Try / catch
try {
registry.register(fileWatcherProvider);
} catch (NullPointerException e) {
if (e.getMessage() != null && e.getMessage().contains("is required in the config")) {
logger.error("file_watcher config missing trust anchor: add ca_certificate_file or spiffe_trust_bundle_map_file", e);
}
throw e;
} Prevention
- Always include a trust anchor key in file_watcher configs when SPIFFE is enabled
- Lint bootstrap certProviders JSON in CI for required keys
- Keep deployment templates in sync with the provider's expected config schema
When it happens
Trigger: Enabling SPIFFE and registering a file_watcher provider whose config JSON contains certificate_file and private_key_file but lacks both 'ca_certificate_file' and 'spiffe_trust_bundle_map_file'; thrown from validateAndTranslateConfig during config parsing (called via configObj).
Common situations: Cert configs copied from non-SPIFFE examples missing trust roots; bootstrap certProviders entries where only client cert/key files were specified; migration to SPIFFE trust bundles where the root file key was renamed.
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.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Provider not found for ${pluginName}
- CertificateProvider instance name '${certInstanceName}' not
- ca_certificate_provider_instance name '${rootCaInstanceName}
- Fail to read bootstrap file
- No xds servers found for authority
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/a8eb0d9cc863ae1a.
Report an issue: GitHub.