slackhq/nebula · error
ErrBadFormat
ErrBadFormat
Error message
bad wire format
What it means
ErrBadFormat signals that an input byte slice is not a well-formed Nebula v2 certificate wire format. unmarshalCertificateV2 rejects buffers that are empty, exceed MaxCertificateSize, or whose ASN.1 DER envelope cannot be parsed as the expected SEQUENCE structure.
Source
Thrown at cert/errors.go:9
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")View on GitHub (pinned to dd8f660c0a)
Solutions
- Verify the bytes are the raw DER payload of a v2 certificate, not the PEM text — decode the PEM block first (pem.Decode) and pass block.Bytes.
- Check len(b) > 0 and len(b) <= MaxCertificateSize before calling.
- Confirm the peer / file is actually serving a Nebula v2 certificate; v1 certs must be decoded with the v1 unmarshal path.
- Inspect the source of the bytes for truncation or corruption (log the length and first bytes).
Example fix
// before
raw, _ := os.ReadFile("ca.crt")
c, err := cert.UnmarshalCertificateV2(raw)
// after
block, _ := pem.Decode(raw)
c, err := cert.UnmarshalCertificateV2(block.Bytes)
if err != nil { ... } Defensive patterns
Strategy: validation
Validate before calling
if len(b) == 0 || len(b) > cert.MaxCertificateSize {
return fmt.Errorf("cert payload: got %d bytes", len(b))
} Type guard
func isPlausibleCertBytes(b []byte) bool {
return len(b) > 0 && len(b) <= cert.MaxCertificateSize && b[0] == 0x30 // DER SEQUENCE
} Try / catch
c, err := cert.UnmarshalCertificateV2(b)
if errors.Is(err, cert.ErrBadFormat) {
return fmt.Errorf("not a v2 nebula certificate (%d bytes); check PEM decoding", len(b))
} Prevention
- Always pem.Decode before unmarshaling cert files.
- Check byte length against cert.MaxCertificateSize first.
- Confirm certificate version (v1 vs v2) and use the matching unmarshal API.
When it happens
Trigger: Calling unmarshalCertificateV2 / unmarshalDetails with a zero-length byte slice, a byte slice larger than MaxCertificateSize, or bytes whose DER envelope is not an ASN.1 SEQUENCE or has an empty body (cert/cert_v2.go:573-579).
Common situations: Loading a v1 certificate or a PEM-encoded file without stripping the PEM armor before passing raw bytes; truncated network transmission; pointing a config field at a non-certificate file; receiving garbage on the handshake channel.
Related errors
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/c1b8e6723eff2853.
Report an issue: GitHub.