slackhq/nebula · error
nil byte array
Error message
nil byte array
What it means
unmarshalCertificateV1 refuses to decode an empty protobuf byte slice; there is nothing to unmarshal so it returns 'nil byte array' immediately. This fails fast before attempting protobuf parsing so callers get a clear message instead of a generic proto error.
Source
Thrown at cert/cert_v1.go:404
if err != nil {
return nil, err
}
return b, nil
}
func (c *certificateV1) setSignature(b []byte) error {
if len(b) == 0 {
return ErrEmptySignature
}
c.signature = b
return nil
}
// unmarshalCertificateV1 will unmarshal a protobuf byte representation of a nebula cert
// if the publicKey is provided here then it is not required to be present in `b`
func unmarshalCertificateV1(b []byte, publicKey []byte) (*certificateV1, error) {
if len(b) == 0 {
return nil, fmt.Errorf("nil byte array")
}
var rc RawNebulaCertificate
err := proto.Unmarshal(b, &rc)
if err != nil {
return nil, err
}
if rc.Details == nil {
return nil, fmt.Errorf("encoded Details was nil")
}
if len(rc.Details.Ips)%2 != 0 {
return nil, fmt.Errorf("encoded IPs should be in pairs, an odd number was found")
}
if len(rc.Details.Subnets)%2 != 0 {
return nil, fmt.Errorf("encoded Subnets should be in pairs, an odd number was found")
}View on GitHub (pinned to dd8f660c0a)
Solutions
- Check len(b) > 0 before calling unmarshalCertificateV1 and surface a caller-appropriate error
- Fix the upstream read (file, network, KV) that produced empty bytes; check read errors
- Re-obtain or re-issue the certificate if the source data is genuinely empty
- Add logging of the byte-slice source path/key to find why it is empty
Example fix
// before
if len(rawCert) == 0 {
// silently calls unmarshal, gets 'nil byte array'
}
c, err := unmarshalCertificateV1(rawCert, nil)
// after
if len(rawCert) == 0 {
return nil, fmt.Errorf("certificate data from %s is empty", certPath)
}
c, err := unmarshalCertificateV1(rawCert, nil) Defensive patterns
Strategy: validation
Validate before calling
if len(rawCertBytes) == 0 {
return nil, fmt.Errorf("certificate source %s produced no bytes", source)
}
c, err := unmarshalCertificateV1(rawCertBytes, nil) Type guard
func hasCertBytes(b []byte) bool { return len(b) > 0 } Try / catch
c, err := unmarshalCertificateV1(rawCertBytes, nil)
if err != nil {
if strings.Contains(err.Error(), "nil byte array") {
return nil, fmt.Errorf("certificate data is empty; check the source read")
}
return nil, err
} Prevention
- Check the error return of every file/network read feeding the cert bytes
- Validate non-empty certificate data at config-load time
- Alert on zero-byte certificate files on disk
- Wrap unmarshalCertificateV1 with a helper that enriches empty-input errors
When it happens
Trigger: Passing an empty (len==0) byte slice to unmarshalCertificateV1 via Recombine, unmarshalCertificateBlock, or directly; e.g. a zero-byte certificate file, an empty protobuf field, or a helper returning no bytes.
Common situations: Certificate file truncated to zero bytes on disk; failed read treated as success; empty value pulled from a key-value store; a nil/empty raw certificate field in a bundle being recombined.
Related errors
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/d23a0ae3c812896d.
Report an issue: GitHub.