grpc/grpc-go · error

spiffe: BundleMapFromBytes() failed to parse bundle for trus

Error message

spiffe: BundleMapFromBytes() failed to parse bundle for trust domain %q: %v

What it means

Returned when spiffebundle.Parse fails for an individual trust domain entry inside the Bundle Map. After the key validates, the value is handed to the go-spiffe bundle parser which expects X.509 authorities (as DER or PEM cert array) and optional JWT keys; malformed certs, missing required fields, or wrong JSON shapes trigger this error wrapping the underlying parse failure.

Source

Thrown at internal/credentials/spiffe/spiffe.go:59

// 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.
func GetRootsFromSPIFFEBundleMap(bundleMap map[string]*spiffebundle.Bundle, leafCert *x509.Certificate) (*x509.CertPool, error) {
	// 1. Upon receiving a peer certificate, verify that it is a well-formed SPIFFE
	//    leaf certificate.  In particular, it must have a single URI SAN containing
	//    a well-formed SPIFFE ID ([SPIFFE ID format]).
	spiffeID, err := idFromCert(leafCert)
	if err != nil {
		return nil, fmt.Errorf("spiffe: could not get spiffe ID from peer leaf cert but verification with spiffe trust map was configured: %v", err)
	}

	// 2. Use the trust domain in the peer certificate's SPIFFE ID to lookup

View on GitHub (pinned to 03255a9237)

Solutions

  1. Re-fetch the bundle for that trust domain from its authoritative source (SPIRE bundle endpoint).
  2. Verify the x509_authorities entries parse with crypto/x509 before packaging them.
  3. Ensure DER certs are base64-encoded as the SPIFFE bundle JSON spec requires.
  4. Diff the offending bundle against a known-good one to spot truncation or encoding regressions.

Example fix

// before
{"trust_domains": {"prod": {"x509_authorities": "not-a-cert"}}}

// after
{"trust_domains": {"prod": {"x509_authorities": [{"x509_asn": "<base64-DER>"}]}}}
Defensive patterns

Strategy: try-catch

Validate before calling

func bundlesParse(b map[string]*spiffebundle.Bundle, raw []byte) error {
    var pm struct{ TrustDomains map[string]json.RawMessage `json:"trust_domains"` }
    if err := json.Unmarshal(raw, &pm); err != nil { return err }
    for td, jb := range pm.TrustDomains {
        if _, err := spiffebundle.Parse(spiffeid.RequireTrustDomainFromString(td), jb); err != nil {
            return fmt.Errorf("trust domain %s: %w", td, err)
        }
    }
    return nil
}

Try / catch

bm, err := spiffe.BundleMapFromBytes(raw)
if err != nil {
    if strings.Contains(err.Error(), "failed to parse bundle") {
        // identify the offending trust domain from the error, re-fetch just that bundle
    }
    return err
}

Prevention

When it happens

Trigger: A trust_domains entry whose value is not a valid SPIFFE bundle object: e.g. x509_authorities not present or containing non-PEM/non-base64 data, a JSON array where an object is expected, expired/revoked cert bytes that x509.ParseCertificate rejects.

Common situations: Truncated bundle file; copy/paste of a PEM block that lost its BEGIN/END markers; mismatch between the bundle version produced by an old SPIRE and the parser's expectations; encoding issues (raw bytes instead of base64 DER).

Understand the failure class

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/a5c3046ee2f0159a. Report an issue: GitHub.