nats-io/nats-server · error · JSConsumerInvalidPolicyError
10094
10094
Error message
consumer delivery policy is deliver last per subject, but FilterSubject is not set
What it means
JSConsumerInvalidPolicyError (API error 10094): the consumer create/update handler rejects a configuration whose DeliverPolicy is DeliverLastPerSubject without any subject filter. DeliverLastPerSubject needs a filter to know which subjects to track; with no FilterSubject/FilterSubjects it is an unresolvable policy, so the request fails.
Source
Thrown at server/jetstream_cluster.go:11435
total++
if selectedTier == _EMPTY_ || isSameTier(ca.Config.replicas(&streamCfg), selectedReplicas) {
tierTotal++
}
}
}
if (streamMaxc > 0 && total >= streamMaxc) || (tierMaxc > 0 && tierTotal >= tierMaxc) {
resp.Error = NewJSMaximumConsumersLimitError()
s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
return
}
}
}
}
// Also short circuit if DeliverLastPerSubject is set with no FilterSubject.
if cfg.DeliverPolicy == DeliverLastPerSubject {
if cfg.FilterSubject == _EMPTY_ && len(cfg.FilterSubjects) == 0 {
resp.Error = NewJSConsumerInvalidPolicyError(fmt.Errorf("consumer delivery policy is deliver last per subject, but FilterSubject is not set"))
s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
return
}
}
// Setup proper default for ack wait if we are in explicit ack mode.
if cfg.AckWait == 0 && (cfg.AckPolicy == AckExplicit || cfg.AckPolicy == AckAll) {
cfg.AckWait = JsAckWaitDefault
}
// Setup default of -1, meaning no limit for MaxDeliver.
if cfg.MaxDeliver == 0 {
cfg.MaxDeliver = -1
}
// Set proper default for max ack pending if we are ack explicit and none has been set.
if cfg.AckPolicy == AckExplicit && cfg.MaxAckPending == 0 {
cfg.MaxAckPending = JsDefaultMaxAckPending
}
View on GitHub (pinned to 3a66a489d2)
Solutions
- Set FilterSubject (e.g. `orders.>`) in the consumer config, or add entries to FilterSubjects.
- If no filter is wanted, switch DeliverPolicy to DeliverLast or DeliverAll instead of DeliverLastPerSubject.
- Add a pre-submission validation that pairs DeliverLastPerSubject with a non-empty filter.
Example fix
// before
cc := &nats.ConsumerConfig{DeliverPolicy: nats.DeliverLastPerSubject}
// after
cc := &nats.ConsumerConfig{
DeliverPolicy: nats.DeliverLastPerSubject,
FilterSubject: "events.>",
} Defensive patterns
Strategy: validation
Validate before calling
// Go client: guard before creating the consumer
if cc.DeliverPolicy == nats.DeliverLastPerSubject && cc.FilterSubject == "" && len(cc.FilterSubjects) == 0 {
return errors.New("DeliverLastPerSubject requires FilterSubject or FilterSubjects")
} Type guard
func validDeliverLastPerSubject(cc *nats.ConsumerConfig) bool {
if cc.DeliverPolicy != nats.DeliverLastPerSubject {
return true
}
return cc.FilterSubject != "" || len(cc.FilterSubjects) > 0
} Try / catch
_, err := js.CreateConsumer(nc, stream, cfg)
var apiErr *nats.APIError
if errors.As(err, &apiErr) && apiErr.ErrorCode == 10094 {
cfg.FilterSubject = "events.>" // or switch DeliverPolicy
_, err = js.CreateConsumer(nc, stream, cfg)
} Prevention
- Always pair DeliverLastPerSubject with an explicit subject filter.
- Use a config struct wrapper that validates deliver policy/filter combinations.
- Lint consumer configs in CI before deployment.
- Default to DeliverLast/DeliverAll when no filter is needed.
When it happens
Trigger: Creating a consumer (push or pull) via `$JS.API.CONSUMER.CREATE.*`, `jetstream.CreateConsumer`, or `js.AddConsumer` with `DeliverPolicy: DeliverLastPerSubject` while leaving `FilterSubject` empty (and no `FilterSubjects`).
Common situations: Copy-pasted consumer configs where the filter was removed; code paths that compute the deliver policy dynamically but only sometimes set a filter; tooling migrating consumers to 'last per subject' semantics.
Related errors
- max_request_batch must be set if it's JetStream limits are s
- consumer name can not contain '.', '*', '>', '\', '/'
- consumer durable name can not contain '.', '*', '>', '\', '/
- 10052
- 10069
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/5eb02917a5bbb789.
Report an issue: GitHub.