JetStream 2.15 clustered snapshots can contain unnamed consumers and fail restore

Author: RainyPixelCreated Sep 25, 2026Updated Sep 30, 2026

Version

nats-server v2.15.0 (eb76367), clustered JetStream R3. The snapshots were taken with the 2.15 API through NATS CLI. nats backup validate from NATS CLI v0.5.0 independently rejects them. I observed the failure in repeated snapshots of two different active streams.

Actual behavior

The snapshot API reports success, but the resulting NATSARC1 archive contains an entry named exactly consumers (without / and a consumer name). Its state.json counts that entry as a consumer. The record's config.name is empty. The archive may also contain valid consumers/<name> entries and messages.

Validation fails with:

expected consumer entry (... remaining), found "consumers"

Restoring into a fresh, isolated v2.15.0 server also fails:

restore failed: expected consumer, found "consumers" (10062)

Other streams from the same cluster, without such entries, pass validation. The failure was seen on streams with active ephemeral consumers; I have not reproduced it on a standalone server with a single ephemeral consumer.

Expected behavior

A successful snapshot should always pass nats backup validate and be restorable. If a consumer cannot be represented, the snapshot request should fail rather than return an unusable archive.

Suspected cause

In server/stream_backup.go, clustered snapshots copy consumerAssignment.Config, then writeConsumerMsg uses path.Join("consumers", scs.Name). For some clustered ephemeral assignments, Config.Name is empty even though consumerAssignment.Name identifies the consumer. This writes the bare consumers path. The restore path requires consumers/ as a prefix and rejects the archive.

No production payloads or credentials are included here. I can provide a sanitized archive structure or additional metadata if helpful.