grpc/grpc-go · error

spiffe: BundleMapFromBytes() no bundles parsed from spiffe b

Error message

spiffe: BundleMapFromBytes() no bundles parsed from spiffe bundle map bytes

What it means

Returned by spiffe.BundleMapFromBytes when the JSON document either is not an object containing a 'trust_domains' key or that key resolves to null. Per the SPIFFE Bundle Map spec the top-level shape must be {"trust_domains": {"<td>": {<bundle>}, ...}}, so an entirely missing or empty trust_domains map yields this error. It signals the input is structurally not a SPIFFE Bundle Map.

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 03255a9237)

Solutions

  1. Confirm the input is a Bundle Map by checking for the top-level "trust_domains" object key.
  2. If you have a single-domain bundle, wrap it: build the map {"trust_domains": {"<domain>": <bundle-json>}} before passing it in.
  3. Fetch from a SPIFFE Bundle Map endpoint rather than a per-domain bundle endpoint.
  4. Dump the first bytes and validate it parses as JSON with the expected schema before calling BundleMapFromBytes.

Example fix

// before
map, err := spiffe.BundleMapFromBytes(singleBundleBytes) // wrong shape

// after
wrapped := fmt.Sprintf(`{"trust_domains":{"%s":%s}}`, td, string(singleBundleBytes))
map, err := spiffe.BundleMapFromBytes([]byte(wrapped))
Defensive patterns

Strategy: validation

Validate before calling

func isSPIFFEBundleMap(b []byte) error {
    var probe struct{ TrustDomains json.RawMessage `json:"trust_domains"` }
    if err := json.Unmarshal(b, &probe); err != nil { return err }
    if len(probe.TrustDomains) == 0 || string(probe.TrustDomains) == "null" {
        return errors.New("not a SPIFFE Bundle Map: missing or null trust_domains")
    }
    return nil
}

Type guard

func looksLikeBundleMap(b []byte) bool {
    var probe struct{ TrustDomains json.RawMessage `json:"trust_domains"` }
    return json.Unmarshal(b, &probe) == nil && len(probe.TrustDomains) > 0 && string(probe.TrustDomains) != "null"
}

Try / catch

bm, err := spiffe.BundleMapFromBytes(raw)
if err != nil {
    if strings.Contains(err.Error(), "no bundles parsed") {
        // log input length/preview and re-fetch from the bundle endpoint
    }
    return err
}

Prevention

When it happens

Trigger: Passing bytes that are a single SPIFFE Bundle (not a Bundle Map), a PEM certificate blob, an empty byte slice whose JSON is '{}', or a misnamed key like "bundles" instead of "trust_domains". The check is `if result.Bundles == nil` after json.Unmarshal into partialParsedSPIFFEBundleMap.

Common situations: Confusing SPIFFE Bundle (one trust domain) with SPIFFE Bundle Map (many); loading the wrong file from a SPIRE workload agent; fetching from a bundle endpoint that returns a single bundle; version skew between the bundle producer and this consumer.

Related errors


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