slackhq/nebula · error
ErrNotSelfSigned
ErrNotSelfSigned
Error message
certificate is not self-signed
What it means
ErrNotSelfSigned is returned by CAPool.AddCA when the candidate CA certificate's signature cannot be verified with its own public key (CheckSignature(c.PublicKey()) fails). A trust anchor must be self-signed.
Source
Thrown at cert/errors.go:13
package cert
import (
"errors"
"fmt"
)
var (
ErrBadFormat = errors.New("bad wire format")
ErrRootExpired = errors.New("root certificate is expired")
ErrExpired = errors.New("certificate is expired")
ErrNotCA = errors.New("certificate is not a CA")
ErrNotSelfSigned = errors.New("certificate is not self-signed")
ErrBlockListed = errors.New("certificate is in the block list")
ErrFingerprintMismatch = errors.New("certificate fingerprint did not match")
ErrSignatureMismatch = errors.New("certificate signature did not match")
ErrInvalidPublicKey = errors.New("invalid public key")
ErrInvalidPrivateKey = errors.New("invalid private key")
ErrPublicPrivateCurveMismatch = errors.New("public key does not match private key curve")
ErrPublicPrivateKeyMismatch = errors.New("public key and private key are not a pair")
ErrPrivateKeyEncrypted = errors.New("private key must be decrypted")
ErrCaNotFound = errors.New("could not find ca for the certificate")
ErrUnknownVersion = errors.New("certificate version unrecognized")
ErrCertPubkeyPresent = errors.New("certificate has unexpected pubkey present")
ErrCurveMismatch = errors.New("certificate curve does not match CA")
ErrInvalidPEMBlock = errors.New("input did not contain a valid PEM encoded block")
ErrInvalidPEMCertificateBanner = errors.New("bytes did not contain a proper certificate banner")
ErrInvalidPEMX25519PublicKeyBanner = errors.New("bytes did not contain a proper X25519 public key banner")
ErrInvalidPEMX25519PrivateKeyBanner = errors.New("bytes did not contain a proper X25519 private key banner")
ErrInvalidPEMEd25519PublicKeyBanner = errors.New("bytes did not contain a proper Ed25519 public key banner")View on GitHub (pinned to dd8f660c0a)
Solutions
- Add the root self-signed CA certificate to the pool, not an intermediate or leaf.
- Re-verify the certificate file integrity (checksums, clean re-download).
- If using intermediates, chain them properly and add only the self-signed root to CAPool.
- Handle the wrapped format with errors.Is(err, cert.ErrNotSelfSigned) since AddCA wraps it with the cert name.
Example fix
// before pool.AddCA(intermediateCert) // not self-signed // after pool.AddCA(rootCACert) // self-signed trust anchor
Defensive patterns
Strategy: validation
Validate before calling
if !c.CheckSignature(c.PublicKey()) {
return fmt.Errorf("%s is not self-signed; add the root CA instead", c.Name())
} Type guard
func isSelfSigned(c cert.Certificate) bool {
return c.CheckSignature(c.PublicKey())
} Try / catch
err := pool.AddCA(c)
if errors.Is(err, cert.ErrNotSelfSigned) {
return fmt.Errorf("%s is signed by another CA; load the self-signed root", c.Name())
} Prevention
- Only load root trust anchors into CAPool.
- Verify self-signedness of any cert you add to a pool.
- Checksum cert files after distribution to catch corruption.
When it happens
Trigger: pool.AddCA(c) is called and c.CheckSignature(c.PublicKey()) returns false — i.e., the cert was signed by another key rather than its own, or the signature bytes/cipher are corrupt.
Common situations: Adding an intermediate or leaf certificate (signed by the root) directly into the pool instead of the self-signed root; corrupted cert bytes; certs hand-mangled during distribution.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- ErrNotCA
- ErrSignatureMismatch
- ErrEmptySignature
- %s: %w
- could not calculate fingerprint for provided CA; error: %w;
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/ea4dcd01a5da2d0c.
Report an issue: GitHub.