nats-io/nats-server · error · ApiError

consumer name can not contain '.', '*', '>', '\', '/'

Error message

consumer name can not contain '.', '*', '>', '\', '/'

What it means

The consumer's Name field failed isValidAssetName, meaning it contains one of the forbidden characters '.', '*', '>', '\\' or '/'. JetStream asset names are used directly as NATS subjects/tokens, so these wildcard and path characters are rejected. The server returns this wrapped in a JSStreamInvalidConfigError during consumer config validation.

Source

Thrown at server/consumer.go:739

	if config.AckPolicy == AckFlowControl && !pedantic {
		config.FlowControl = true
		config.Heartbeat = sourceHealthHB
	}
	return nil
}

// Check the consumer config. If we are recovering don't check filter subjects.
func checkConsumerCfg(
	config *ConsumerConfig,
	srvLim *JSLimitOpts,
	cfg *StreamConfig,
	_ *Account,
	accLim *JetStreamAccountLimits,
	isRecovering bool,
) *ApiError {

	if config.Name != _EMPTY_ && !isValidAssetName(config.Name) {
		return NewJSStreamInvalidConfigError(errors.New("consumer name can not contain '.', '*', '>', '\\', '/'"))
	}
	if config.Durable != _EMPTY_ && !isValidAssetName(config.Durable) {
		return NewJSStreamInvalidConfigError(errors.New("consumer durable name can not contain '.', '*', '>', '\\', '/'"))
	}

	// Check if replicas is defined but exceeds parent stream.
	if config.Replicas > 0 && config.Replicas > cfg.Replicas {
		return NewJSConsumerReplicasExceedsStreamError()
	}
	// Check that it is not negative
	if config.Replicas < 0 {
		return NewJSReplicasCountCannotBeNegativeError()
	}
	// If the stream is interest or workqueue retention make sure the replicas
	// match that of the stream. This is REQUIRED for now.
	if cfg.Retention == InterestPolicy || cfg.Retention == WorkQueuePolicy {
		// Only error here if not recovering.
		// We handle recovering in a different spot to allow consumer to come up

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Sanitize the consumer name, replacing '.', '*', '>', '\\' and '/' with allowed characters such as '-' or '_'.
  2. Generate a name programmatically (e.g. hash or slug) when the source string may contain reserved characters.
  3. Validate names client-side before calling the API.
  4. If a dotted name is required, leave Name empty and set only Durable (also subject to the same rule) or let the server assign one.

Example fix

// before
cc := &nats.ConsumerConfig{Name: "orders/eu.consumer"}
// after
cc := &nats.ConsumerConfig{Name: "orders-eu-consumer"}
Defensive patterns

Strategy: validation

Validate before calling

var invalidAssetNameRe = regexp.MustCompile(`[.*>\\/]`)
func validConsumerName(name string) bool {
	return name == "" || !invalidAssetNameRe.MatchString(name)
}
if !validConsumerName(cc.Name) {
	return fmt.Errorf("invalid consumer name %q", cc.Name)
}

Prevention

When it happens

Trigger: Any consumer create/update API call (js.AddConsumer, $JS.API.CONSUMER.CREATE.<stream>.<name>) where config.Name is non-empty and contains '.', '*', '>', '\\' or '/'.

Common situations: Deriving consumer names from user input, file paths, or topic names containing dots/slashes; building names like 'app.consumer.v1' with slashes from URLs; accidentally passing a subject instead of a name.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/96f6286114bce6f2. Report an issue: GitHub.