{"record":{"id":"d40987cd8acbba75","repo":"nats-io/nats-server","slug":"errnilheader","errorCode":"ErrNilHeader","errorMessage":"archive: nil header","messagePattern":"archive: nil header","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/archive/archive.go","lineNumber":36,"sourceCode":"\t\"encoding/binary\"\n\t\"errors\"\n\t\"io\"\n)\n\nconst MagicBytes = \"NATSARC1\"\n\n// maxNameLen bounds the entry name length accepted when reading an archive,\n// avoiding an unbounded allocation on corrupt or malicious input. The name is\n// the only variable-length field read directly from the stream.\nconst maxNameLen = 1 << 20\n\nvar (\n\tErrClosed            = errors.New(\"archive: closed\")\n\tErrInvalidArchive    = errors.New(\"archive: invalid archive stream\")\n\tErrIncompleteEntry   = errors.New(\"archive: entry not fully written\")\n\tErrNoActiveEntry     = errors.New(\"archive: no active entry\")\n\tErrWriteTooLong      = errors.New(\"archive: write exceeds declared entry size\")\n\tErrNilHeader         = errors.New(\"archive: nil header\")\n\tErrNegativeEntrySize = errors.New(\"archive: negative entry size\")\n)\n\n// Header describes one archive entry.\n//\n// On the wire each entry is the encoded header fields followed by the payload.\n// HeaderSize and PayloadSize describe how that payload is split (e.g. message\n// headers vs. body); the payload length is their sum and is not stored\n// separately. Sequence is always encoded, with 0 meaning \"unset\".\ntype Header struct {\n\tName        string\n\tHeaderSize  int64\n\tPayloadSize int64\n\tTimestamp   int64\n\tSequence    uint64\n}\n\nfunc (h *Header) clone() *Header {","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/archive/archive.go#L18-L54","documentation":"ErrNilHeader means Writer.WriteHeader was called with a nil *Header pointer. The Writer cannot encode an entry without its metadata (name, sizes, timestamp, sequence), so a nil argument is rejected immediately before anything is written to the underlying stream.","triggerScenarios":"Writer.WriteHeader(nil) — typically when the Header was produced by a function that can return nil on an error path (e.g. Reader.Next returning nil on EOF) and the error was not checked before passing it along.","commonSituations":"Copy-piping entries from a Reader to a Writer: `hdr, err := r.Next(); w.WriteHeader(hdr)` without checking err (Next returns nil header on io.EOF or ErrInvalidArchive); an uninitialized struct pointer that was never assigned; a lookup/map miss returning a nil *Header.","solutions":["Check the error from the Header's producing call before calling WriteHeader; never pass a possibly-nil pointer.","Skip or break the loop on io.EOF from Reader.Next instead of forwarding the nil header.","Construct and validate the Header explicitly (name, non-negative sizes) before calling WriteHeader."],"exampleFix":"// before\nh, _ := r.Next()\nw.WriteHeader(h) // io.EOF -> ErrNilHeader\n// after\nh, err := r.Next()\nif err != nil { return err }\nif h == nil { return nil }\nif err := w.WriteHeader(h); err != nil { return err }","handlingStrategy":"validation","validationCode":"if hdr == nil {\n    return errors.New(\"cannot start archive entry: header is nil\")\n}\nif hdr.HeaderSize < 0 || hdr.PayloadSize < 0 {\n    return errors.New(\"negative entry size\")\n}","typeGuard":null,"tryCatchPattern":"if err := w.WriteHeader(hdr); err != nil {\n    if errors.Is(err, archive.ErrNilHeader) {\n        return fmt.Errorf(\"WriteHeader got nil header; check the error from the Header source\")\n    }\n    return err\n}","preventionTips":["Always check the error from Reader.Next (or any Header producer) before using the returned header — it is nil on io.EOF and errors.","Break on io.EOF in reader-to-writer copy loops instead of forwarding the nil header.","Validate headers (non-nil, non-negative sizes) in a helper before WriteHeader."],"tags":["go","archive","writer","nil-pointer","api-misuse"],"backgroundTag":"nil-header","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}