{"record":{"id":"87ce94abaf1e4d00","repo":"nats-io/nats-server","slug":"errnoactiveentry","errorCode":"ErrNoActiveEntry","errorMessage":"archive: no active entry","messagePattern":"archive: no active entry","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/archive/archive.go","lineNumber":34,"sourceCode":"import (\n\t\"bufio\"\n\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}","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/archive/archive.go#L16-L52","documentation":"ErrNoActiveEntry means Writer.Write was called without an open archive entry. Every payload byte must belong to an entry started by WriteHeader; after an entry's declared size is fully written, the Writer clears its internal header, so further Writes are rejected. It is an API-misuse error on the write side of the archive format.","triggerScenarios":"Writer.Write(p) called before any WriteHeader; Write called after the current entry's remaining bytes reached 0 (header auto-cleared, e.g. a zero-size entry or after writing the exact declared payload); Write called on a brand-new Writer with only a stale header pointer.","commonSituations":"Wrapping the Writer in an io.MultiWriter or passing it where an io.Writer is expected and writing preamble/metadata bytes outside of any entry; a caller that keeps writing after the payload loop ended (off-by-one or trailing newline flush); reusing a Writer variable whose last entry already completed.","solutions":["Call WriteHeader with a valid Header before every run of Write calls.","Match Write calls 1:1 with entries: stop writing once you've written HeaderSize+PayloadSize bytes for the current entry.","If bytes must precede the first entry, wrap a separate io.Writer for them; the archive stream itself must start with entries (the Writer emits the magic on the first WriteHeader).","Track a 'current entry open' flag in your code mirroring a.header != nil."],"exampleFix":"// before\nw := archive.NewWriter(f)\nw.Write(payload) // ErrNoActiveEntry\n// after\nw := archive.NewWriter(f)\nif err := w.WriteHeader(&archive.Header{Name: \"entry\", HeaderSize: 0, PayloadSize: int64(len(payload))}); err != nil { return err }\nif _, err := w.Write(payload); err != nil { return err }","handlingStrategy":"validation","validationCode":"// guard your own write helper\nfunc writeEntry(w *archive.Writer, h *archive.Header, payload []byte) error {\n    if h == nil { return errors.New(\"nil header\") }\n    if err := w.WriteHeader(h); err != nil { return err }\n    _, err := w.Write(payload)\n    return err\n}","typeGuard":null,"tryCatchPattern":"if _, err := w.Write(p); err != nil {\n    if errors.Is(err, archive.ErrNoActiveEntry) {\n        return fmt.Errorf(\"Write called outside an entry; call WriteHeader first\")\n    }\n    return err\n}","preventionTips":["Never hand the archive Writer to code expecting a raw io.Writer; wrap it in an entry-scoped writer that asserts WriteHeader was called.","Stop writing as soon as the declared payload bytes are consumed — the Writer clears its entry at remaining==0.","Structure code as one function per entry: WriteHeader, write payload, return."],"tags":["go","archive","writer","api-misuse"],"backgroundTag":"missing-writeheader","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}