{"record":{"id":"8b4c74256e252dc3","repo":"nats-io/nats-server","slug":"consumer-q-is-missing-state","errorCode":null,"errorMessage":"consumer %q is missing state","messagePattern":"consumer %q is missing state","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/stream_backup.go","lineNumber":432,"sourceCode":"\t\t\treturn nil, err\n\t\t}\n\t\tname, found := strings.CutPrefix(hdr.Name, \"consumers/\")\n\t\tif !found {\n\t\t\treturn nil, fmt.Errorf(\"expected consumer, found %q\", hdr.Name)\n\t\t}\n\t\tbuf, err := io.ReadAll(tr)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to read consumer %q state: %w\", name, err)\n\t\t}\n\t\tvar consumer SnapshotConsumerState\n\t\tif err := json.Unmarshal(buf, &consumer); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to decode consumer %q state: %w\", name, err)\n\t\t}\n\t\tif consumer.ConsumerConfig == nil {\n\t\t\treturn nil, fmt.Errorf(\"consumer %q is missing config\", name)\n\t\t}\n\t\tif consumer.ConsumerState == nil {\n\t\t\treturn nil, fmt.Errorf(\"consumer %q is missing state\", name)\n\t\t}\n\t\tisEphemeral := !isDurableConsumer(consumer.ConsumerConfig)\n\t\tif isEphemeral {\n\t\t\t// Keep ephemerals alive and interested until all messages have\n\t\t\t// been restored, then start their normal inactivity lifecycle.\n\t\t\tconsumer.Durable = name\n\t\t}\n\t\to, err := mset.addConsumerForRestore(consumer.ConsumerConfig)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to add consumer %q: %w\", name, err)\n\t\t}\n\t\tif isEphemeral {\n\t\t\tephemerals = append(ephemerals, o)\n\t\t}\n\t\trestoredConsumers = append(restoredConsumers, o)\n\t\to.mu.Lock()\n\t\terr = o.setStoreState(consumer.ConsumerState)\n\t\to.mu.Unlock()","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/stream_backup.go#L414-L450","documentation":"Validation guard in RestoreStreamV2: the decoded SnapshotConsumerState for consumers/<name> has a non-nil config but a nil ConsumerState. The archive entry is incomplete — every snapshot consumer entry must include both a config and a state — so the consumer cannot be recreated with correct delivered/ack floors.","triggerScenarios":"Thrown at server/stream_backup.go:432 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Re-create the backup with the same server version that produced the original stream","Inspect the consumers/<name> JSON entry and confirm the state field is present and non-null","Ensure the archive was not truncated mid-entry during creation or transfer"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}