nats-io/nats-server · error · ApiError

max_batch must not be negative

Error message

max_batch must not be negative

What it means

A JetStream pedantic validation error thrown when MaxRequestBatch (the max number of messages a pull request may batch) is negative. Batch sizes are counts and cannot be negative; in pedantic mode the server refuses the config rather than clamping it to 0 (server default). Thrown from server/consumer.go:634 during consumer create/update validation.

Source

Thrown at server/consumer.go:634

		}
		config.MaxDeliver = -1
	}
	// Setup zero defaults.
	if config.MaxWaiting < 0 {
		if pedantic {
			return NewJSPedanticError(errors.New("max_waiting must not be negative"))
		}
		config.MaxWaiting = 0
	}
	if config.MaxAckPending < -1 {
		if pedantic {
			return NewJSPedanticError(errors.New("max_ack_pending must be set to -1"))
		}
		config.MaxAckPending = -1
	}
	if config.MaxRequestBatch < 0 {
		if pedantic {
			return NewJSPedanticError(errors.New("max_batch must not be negative"))
		}
		config.MaxRequestBatch = 0
	}
	if config.MaxRequestExpires < 0 {
		if pedantic {
			return NewJSPedanticError(errors.New("max_expires must not be negative"))
		}
		config.MaxRequestExpires = 0
	}
	if config.MaxRequestMaxBytes < 0 {
		if pedantic {
			return NewJSPedanticError(errors.New("max_bytes must not be negative"))
		}
		config.MaxRequestMaxBytes = 0
	}
	if config.Heartbeat < 0 {
		if pedantic {
			return NewJSPedanticError(errors.New("idle_heartbeat must not be negative"))

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Set MaxRequestBatch to a positive integer (e.g. 25_000) or 0 to use the server default.
  2. Clamp computed values: if v < 0 { v = 0 } before assigning to MaxRequestBatch.
  3. Remove any explicit negative value from consumer config YAML/JSON or CLI flags.
  4. Run config.Validate(true) client-side before the request to surface it early.

Example fix

// before
batchLimit := configuredBatch - overage // -3
cc := nats.ConsumerConfig{MaxRequestBatch: batchLimit}
// after
if batchLimit < 0 { batchLimit = 0 }
cc := nats.ConsumerConfig{MaxRequestBatch: batchLimit}
Defensive patterns

Strategy: validation

Validate before calling

if cfg.MaxRequestBatch < 0 { return errors.New("max_batch must not be negative") }

Try / catch

if _, err := js.AddConsumer(stream, &cc); err != nil && strings.Contains(err.Error(), "max_batch must not be negative") {
    cc.MaxRequestBatch = 0
    _, err = js.AddConsumer(stream, &cc)
}

Prevention

When it happens

Trigger: ConsumerConfig.MaxRequestBatch < 0 passed to consumer creation/update with pedantic validation enabled, e.g. js.AddConsumer with MaxRequestBatch: -5 or a computed batch limit that went negative.

Common situations: Arithmetic like defaultBatch - extra producing a negative number; config flags such as --max-request-batch=-1; tenants copying other 'unlimited = -1' conventions from fields like MaxAckPending where -1 is legal but here it is not.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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