dgraph-io/dgraph · critical
%s: verification failed
Error message
%s: verification failed
What it means
verifyCert (dgraph/cmd/cert/cert.go:171) wraps the error returned by x509.Certificate.Verify when the freshly created node or client cert fails chain verification against its parent CA (Roots pool built from c.parent). The wrapped err from the stdlib explains the actual cause: expired, unknown authority, wrong key usage, hostname mismatch, etc. It is returned right after cert creation, so it means the new cert is not usable.
Source
Thrown at dgraph/cmd/cert/cert.go:171
roots.AddCert(c.parent)
opts := x509.VerifyOptions{Roots: roots}
if c.hosts != nil {
opts.KeyUsages = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth,
x509.ExtKeyUsageClientAuth}
for i := range c.hosts {
if err := cert.VerifyHostname(c.hosts[i]); err != nil {
return err
}
}
}
if c.client != "" {
opts.KeyUsages = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
}
_, err = cert.Verify(opts)
if err != nil {
return errors.Wrapf(err, "%s: verification failed", certFile)
}
return nil
}
View on GitHub (pinned to 759e242be6)
Solutions
- Read the wrapped x509 error to identify the cause (UnknownAuthority, Expired, IncompatibleKeyUsage).
- Regenerate the full chain together: `dgraph cert --ca --force` then `dgraph cert --node --client --force` so parent and leaves match.
- Verify the files are a matching pair with `dgraph cert --info` or `openssl verify -CAfile ca.crt node.crt`.
- Check clock/NotBefore skew if the error is 'certificate is not valid yet'.
Example fix
# before: mixing an old CA with new node certs dgraph cert --node --force # after: regenerate CA and leaves together dgraph cert --ca --node --client --force
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-verify chain outside the tool before trusting the generated cert
roots := x509.NewCertPool()
ca, _ := readCert("ca.crt")
roots.AddCert(ca)
cert, err := readCert("node.crt")
if err == nil {
if _, err := cert.Verify(x509.VerifyOptions{Roots: roots}); err != nil {
fmt.Println("chain invalid:", err)
}
} Try / catch
if err := verifyCert("node.crt"); err != nil {
var inner error
if unwrapped, ok := err.(*errors.Error); ok && errors.Is(err, x509.CertificateInvalidError{}) {
inner = unwrapped.Unwrap()
}
// inspect inner: UnknownAuthority/Expired/IncompatibleKeyUsage
return fmt.Errorf("regenerate chain: %w", err)
} Prevention
- Regenerate CA and leaf certs together with --force so parent/signer always match.
- Never mix cert files from separate generation runs in the same tls directory.
- Keep NTP/clock sync enabled on hosts issuing and verifying certs.
- Verify with `openssl verify -CAfile ca.crt node.crt` after generation.
When it happens
Trigger: createNodePair or createClientPair generates a cert and then calls verifyCert; cert.Verify fails because the CA expired, the CA cert is not the actual signer, the cert's KeyUsages don't match the requested ExtKeyUsage (ServerAuth/ClientAuth), or the chain is otherwise untrusted (e.g. mismatched ca.crt/key or corrupted files).
Common situations: ca.crt was regenerated after the node/client cert, so the signer no longer matches; mixing files from different --force regenerations; system clock skew making certs not-yet-valid or expired; manually edited/re-issued certs with mismatched key usage.
Related errors
- --duration: certificate expiration date '%s' exceeds parent
- could not read parent cert
- Failed to read key block
- Unknown PEM type: %s
- Key size value is too large (x > 4096)
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/1da0425ce8c78cd4.
Report an issue: GitHub.