grpc/grpc-go · error

input cert has URIs but should have 1

Error message

input cert has %v URIs but should have 1

What it means

Raised by idFromCert when len(cert.URIs) != 1. A conformant SPIFFE leaf certificate must carry exactly one URI SAN holding the SPIFFE ID; zero URIs or two-or-more URIs both violate the spec and are rejected.

Solutions

  1. Re-issue the certificate so the URI SAN list contains exactly one entry, the spiffe:// URI.
  2. Move any non-SPIFFE URIs to a different SAN type or a custom extension.
  3. Confirm the CA (SPIRE/workload registrar) is configured to emit a single URI SAN.
  4. Inspect with: openssl x509 -text -noout | grep -A2 'URI:'.

Example fix

// before: cert URIs = [spiffe://example.org/svc, https://svc/metrics]
// after: cert URIs = [spiffe://example.org/svc]
Defensive patterns

Strategy: type-guard

Validate before calling

func hasOneURISAN(c *x509.Certificate) bool { return c != nil && len(c.URIs) == 1 }

Type guard

func isSingleURISpiffeCert(c *x509.Certificate) bool {
    return c != nil && len(c.URIs) == 1
}

Try / catch

In your verifier, after parsing the leaf, assert len(leaf.URIs)==1; if not, reject with a message naming the actual count before the SPIFFE helper does.

Prevention

When it happens

Trigger: A cert with no URI SAN (traditional cert); a cert with two URI SANs (e.g. a spiffe:// URI plus an http:// metadata URI); a cert generator that attaches the SPIFFE ID alongside other URIs.

Common situations: Using a general-purpose CA that adds extra URI SANs; service mesh issuing a cert with both SPIFFE and non-SPIFFE URIs; legacy cert with only DNS SANs presented where SPIFFE verification is configured.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/cbc8196dd2698c76. Report an issue: GitHub.

Appendix: source

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

		return nil, fmt.Errorf("spiffe: no bundle found for peer certificates trust domain %q but verification with a SPIFFE trust map was configured", spiffeID.TrustDomain().Name())
	}
	roots := spiffeBundle.X509Authorities()
	rootPool := x509.NewCertPool()
	for _, root := range roots {
		rootPool.AddCert(root)
	}
	return rootPool, nil
}

// idFromCert parses the SPIFFE ID from the x509.Certificate. If the certificate
// does not have a valid SPIFFE ID, returns an error.
func idFromCert(cert *x509.Certificate) (*spiffeid.ID, error) {
	if cert == nil {
		return nil, fmt.Errorf("input cert is nil")
	}
	// A valid SPIFFE Certificate should have exactly one URI.
	if len(cert.URIs) != 1 {
		return nil, fmt.Errorf("input cert has %v URIs but should have 1", len(cert.URIs))
	}
	id, err := spiffeid.FromURI(cert.URIs[0])
	if err != nil {
		return nil, fmt.Errorf("invalid spiffeid: %v", err)
	}
	return &id, nil
}

View on GitHub (pinned to 0c51461d27)