thanos-io/thanos · error

could not get organization field from client cert

Error message

could not get organization field from client cert

What it means

This error comes from getTenantFromCertificate in pkg/tenancy when Thanos extracts a tenant ID from a client TLS certificate. It is thrown when the certificate's Subject.Organization field is empty even though the tenancy configuration specifies 'organization' as the cert field to use for tenant identification. The request is rejected because no tenant can be derived.

Solutions

  1. Set the Organization field in the client certificate Subject and reissue/re-sign the cert (e.g. openssl -subj '/O=my-tenant/CN=client')
  2. Alternatively configure the server to read a field the cert actually has, e.g. --tenant-certificate-field=organizationalUnit or common-name
  3. Verify the presented cert with 'openssl x509 -in client.crt -noout -subject' to confirm which fields exist
  4. Ensure the proxy is receiving the leaf client cert (TLS client auth enabled and PeerCertificates populated)

Example fix

// before
openssl req -new -newkey rsa:2048 -nodes -keyout client.key -out client.csr -subj '/CN=client'
// after
openssl req -new -newkey rsa:2048 -nodes -keyout client.key -out client.csr -subj '/O=my-tenant/CN=client'
Defensive patterns

Strategy: validation

Validate before calling

// Go, before connecting
if len(cert.Subject.Organization) == 0 {
    return errors.New("client cert must have Organization set for tenancy")
}

Type guard

func certHasOrganization(cert *x509.Certificate) bool {
    return cert != nil && len(cert.Subject.Organization) > 0
}

Prevention

When it happens

Trigger: GetTenantFromHTTP is called with certTenantField=CertificateFieldOrganization on an mTLS request whose client certificate has no Organization (O) attribute in its Subject.

Common situations: Client certificates issued without the O field populated (common with internal PKI or cert-manager-generated certs); server configured with --tenant-certificate-field=organization while clients present certs carrying only OU or CN; migration between certificate authorities with different subject templates.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/4dc7a7b70c51d137. Report an issue: GitHub.

Appendix: source

Thrown at pkg/tenancy/tenancy.go:112

}

// getTenantFromCertificate extracts the tenant value from a client's presented certificate. The x509 field to use as
// value can be configured with Options.TenantField. An error is returned when the extraction has not succeeded.
func getTenantFromCertificate(r *http.Request, certTenantField string) (string, error) {
	var tenant string

	if len(r.TLS.PeerCertificates) == 0 {
		return "", errors.New("could not get required certificate field from client cert")
	}

	// First cert is the leaf authenticated against.
	cert := r.TLS.PeerCertificates[0]

	switch certTenantField {

	case CertificateFieldOrganization:
		if len(cert.Subject.Organization) == 0 {
			return "", errors.New("could not get organization field from client cert")
		}
		tenant = cert.Subject.Organization[0]

	case CertificateFieldOrganizationalUnit:
		if len(cert.Subject.OrganizationalUnit) == 0 {
			return "", errors.New("could not get organizationalUnit field from client cert")
		}
		tenant = cert.Subject.OrganizationalUnit[0]

	case CertificateFieldCommonName:
		if cert.Subject.CommonName == "" {
			return "", errors.New("could not get commonName field from client cert")
		}
		tenant = cert.Subject.CommonName

	default:
		return "", errors.New("tls client cert field requested is not supported")
	}

View on GitHub (pinned to 35b8b99117)