A subject rename strands every durable consumer
A durable consumer stores its own subject filter, separate from the stream it belongs to. JetStream refuses to attach a durable whose stored filter differs from the filter the code now asks for. ensure_stream reconciles the stream and nothing reconciled the consumer, so a subject rename left every durable subscriber stranded: js_QueueSubscribe failed, the service exited, and the fleet read one short with nothing in its own log but that one line. Pass the stream name to js_queue_subscribe and the call reconciles the durable first – it reads the stored filter, deletes a consumer whose filter differs, and lets the subscribe recreate it against the current subject.
Why: The consumers live in the JetStream file store and survive restarts, so a rename leaves the old filter behind. The stream is reconciled – ensure_stream compares a stream subjects against the ones asked for and updates them – which makes the rename look finished: the stream carries the new subjects while its consumers still carry the old ones. Measured after the 2026-10-07 subject migration: four stranded consumers across two streams, the two workflow engine durables and the compute wrapper ones, whose filter carries a wildcard over a platform triplet that a stream-level fix cannot reach.
How to apply: Name the stream on every durable subscribe: nats.js_queue_subscribe(subject, durable_name, queue_group, handler, nats.make_stream_name("workflow")). The call then reads the durable stored filter, deletes a consumer whose filter differs, and the subscribe recreates it against the current subject. A caller that passes no stream name keeps the old behaviour and gets no check, which is what an ephemeral or externally managed consumer wants. Deleting the consumer discards its position, so the recreated one delivers from its start policy again; that is at-least-once by design, because a consumer whose filter is wrong has no useful position to keep. To read a stored filter by hand: nats –server $ORES_NATS_URL –tlsca build/keys/nats/ca.crt –tlscert build/keys/nats/<service>.crt –tlskey build/keys/nats/<service>.key consumer info <stream> <durable>. Verified on 2026-10-07: a durable planted on workflow.v1.events.step-completed was replaced on the next workflow service start by one filtered on workflow.v1.ops.step_completed, and the service came up running.