slackhq/nebula · error
nil header
Error message
nil header
What it means
Ad-hoc errors.New("nil header") returned by H.Encode when the header receiver h is nil. It is a nil-receiver guard: encoding a packet header requires a non-nil *H, and calling Encode on a nil header (e.g. a zero-value packet struct) aborts before bytes are written.
Source
Thrown at header/header.go:136
h.Version, h.TypeName(), h.SubTypeName(), h.Reserved, h.RemoteIndex, h.MessageCounter)
}
// MarshalJSON creates a json string representation of a header
func (h *H) MarshalJSON() ([]byte, error) {
return json.Marshal(m{
"version": h.Version,
"type": h.TypeName(),
"subType": h.SubTypeName(),
"reserved": h.Reserved,
"remoteIndex": h.RemoteIndex,
"messageCounter": h.MessageCounter,
})
}
// Encode turns header into bytes
func (h *H) Encode(b []byte) ([]byte, error) {
if h == nil {
return nil, errors.New("nil header")
}
return Encode(b, h.Version, h.Type, h.Subtype, h.RemoteIndex, h.MessageCounter), nil
}
// Parse is a helper function to parses given bytes into new Header struct
func (h *H) Parse(b []byte) error {
if len(b) < Len {
return ErrHeaderTooShort
}
// get upper 4 bytes
h.Version = uint8((b[0] >> 4) & 0x0f)
// get lower 4 bytes
h.Type = MessageType(b[0] & 0x0f)
h.Subtype = MessageSubType(b[1])
h.Reserved = binary.BigEndian.Uint16(b[2:4])
h.RemoteIndex = binary.BigEndian.Uint32(b[4:8])
h.MessageCounter = binary.BigEndian.Uint64(b[8:16])View on GitHub (pinned to dd8f660c0a)
Solutions
- Initialize the header before encoding — ensure the code path always constructs a valid *H
- Check the error from any earlier Parse/build step that produced the header; do not pass a nil result onward
- Add a nil check in the caller before invoking Encode
Example fix
// before
var h *header.H
b, err := h.Encode(buf) // "nil header"
// after
h := &header.H{Version: header.Version, Type: header.Message, Subtype: 0}
b, err := h.Encode(buf) Defensive patterns
Strategy: validation
Validate before calling
if h == nil {
return fmt.Errorf("cannot encode nil header")
} Type guard
func headerReady(h *header.H) bool {
return h != nil
} Try / catch
b, err := h.Encode(buf)
if err != nil {
return fmt.Errorf("header encode: %w", err)
} Prevention
- Always check errors from steps that produce the *H before encoding
- Construct headers via a helper that guarantees a non-nil result
- Guard with a nil check in callers that receive (*H, error)
When it happens
Trigger: Calling Encode on a nil *H — e.g. a header variable that was never populated, or a function returning (*H, error) whose nil result is passed straight to Encode (as in the TestCloseTunnelAuthenticated call path).
Common situations: A build/parse step earlier failed silently and left the header nil; logic error where the header struct was conditionally created; test harness forgetting to initialize the header.
Related errors
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/7c5977adef51653c.
Report an issue: GitHub.