{"record":{"id":"bb421f47f6e6c02c","repo":"nats-io/nats-server","slug":"consumer-q-is-missing-config","errorCode":null,"errorMessage":"consumer %q is missing config","messagePattern":"consumer %q is missing config","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/stream_backup.go","lineNumber":429,"sourceCode":"\tfor range nstate.Consumers {\n\t\thdr, err := tr.Next()\n\t\tif err != nil {\n\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)","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/stream_backup.go#L411-L447","documentation":"Validation guard in RestoreStreamV2: a tar entry under consumers/<name> decoded successfully as JSON, but the resulting SnapshotConsumerState has a nil ConsumerConfig. This means the backup archive is malformed or was produced by a different/incompatible version, since a snapshot consumer entry must always carry a config.","triggerScenarios":"Thrown at server/stream_backup.go:429 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Regenerate the backup archive with a matching server version and retry the restore","Inspect the consumers/<name> entry in the archive to confirm it contains a non-null config object","Verify the archive was not truncated or edited in transit (checksum/transfer integrity)"],"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"}