grpc/grpc-go · error
spiffe: BundleMapFromBytes() no bundles parsed from spiffe…
Error message
spiffe: BundleMapFromBytes() no bundles parsed from spiffe bundle map bytes
What it means
Raised by spiffe.BundleMapFromBytes after JSON unmarshalling succeeded but the `trust_domains` field was absent or null, so result.Bundles is nil. The input bytes are valid JSON but not a SPIFFE Bundle Map per the spec.
Solutions
- Confirm the input is a SPIFFE Bundle Map: a JSON object whose top-level key is `trust_domains` mapping trust-domain names to bundle objects.
- If you actually have a single bundle, parse it with spiffebundle.Parse / spiffebundle.Load instead of BundleMapFromBytes.
- Check the file was mounted/served completely and not truncated to `{}`.
- Validate the JSON has a non-null `trust_domains` key before calling.
Example fix
// before m, err := spiffe.BundleMapFromBytes(singleBundleBytes) // wrong: this is one bundle, not a map // after b, err := spiffebundle.Parse(trustDomain, singleBundleBytes)
Defensive patterns
Strategy: validation
Validate before calling
func isBundleMap(b []byte) bool {
var probe struct{ TrustDomains map[string]json.RawMessage `json:"trust_domains"` }
if err := json.Unmarshal(b, &probe); err != nil { return false }
return probe.TrustDomains != nil
}
// call before spiffe.BundleMapFromBytes Try / catch
If you must call BundleMapFromBytes on untrusted bytes, wrap it: on error fall back to spiffebundle.Parse if the input is actually a single bundle, else propagate the error.
Prevention
- Distinguish single SPIFFE Bundles from SPIFFE Bundle Maps at the file level (different extensions/sources).
- Source bundle maps only from a trusted SPIFFE Bundle Endpoint.
- Reject empty or `{}` inputs before parsing.
When it happens
Trigger: Calling spiffe.BundleMapFromBytes on bytes that are a single SPIFFE Bundle (not a Bundle Map), an empty JSON object `{}`, a JSON with a typo'd key like `"bundles"` instead of `"trust_domains"`, or the JSON value `null`.
Common situations: Loading a bundle file when the bundle-map file was expected; key name mismatch between producer and consumer; feeding an empty/malformed config from a secret mount.
Related errors
- spiffe: BundleMapFromBytes() invalid trust domain
- invalid spiffeid
- spiffe: BundleMapFromBytes() failed to parse bundle for…
- input cert has URIs but should have 1
- input cert is nil
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/c3a60e55c3aa5db8.
Report an issue: GitHub.
Appendix: source
Thrown at internal/credentials/spiffe/spiffe.go:49
)
type partialParsedSPIFFEBundleMap struct {
Bundles map[string]json.RawMessage `json:"trust_domains"`
}
// BundleMapFromBytes parses bytes into a SPIFFE Bundle Map. See the
// SPIFFE Bundle Map spec for more detail -
// https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE_Trust_Domain_and_Bundle.md#4-spiffe-bundle-format
// If duplicate keys are encountered in the JSON parsing, Go's default unmarshal
// behavior occurs which causes the last processed entry to be the entry in the
// parsed map.
func BundleMapFromBytes(bundleMapBytes []byte) (map[string]*spiffebundle.Bundle, error) {
var result partialParsedSPIFFEBundleMap
if err := json.Unmarshal(bundleMapBytes, &result); err != nil {
return nil, err
}
if result.Bundles == nil {
return nil, fmt.Errorf("spiffe: BundleMapFromBytes() no bundles parsed from spiffe bundle map bytes")
}
bundleMap := map[string]*spiffebundle.Bundle{}
for td, jsonBundle := range result.Bundles {
trustDomain, err := spiffeid.TrustDomainFromString(td)
if err != nil {
return nil, fmt.Errorf("spiffe: BundleMapFromBytes() invalid trust domain %q found when parsing SPIFFE Bundle Map: %v", td, err)
}
bundle, err := spiffebundle.Parse(trustDomain, jsonBundle)
if err != nil {
return nil, fmt.Errorf("spiffe: BundleMapFromBytes() failed to parse bundle for trust domain %q: %v", td, err)
}
bundleMap[td] = bundle
}
return bundleMap, nil
}
// GetRootsFromSPIFFEBundleMap returns the root trust certificates from the
// SPIFFE bundle map for the given trust domain from the leaf certificate.View on GitHub (pinned to 0c51461d27)