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

  1. 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.
  2. Check len(b) > 0 and len(b) <= MaxCertificateSize before calling.
  3. Confirm the peer / file is actually serving a Nebula v2 certificate; v1 certs must be decoded with the v1 unmarshal path.
  4. 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

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.