{"record":{"id":"b0991d3ee1c18c2b","repo":"nats-io/nats-server","slug":"max-ack-pending-must-be-set-to-1","errorCode":null,"errorMessage":"max_ack_pending must be set to -1","messagePattern":"max_ack_pending must be set to -1","errorType":"validation","errorClass":"ApiError","httpStatus":null,"severity":"error","filePath":"server/consumer.go","lineNumber":628,"sourceCode":"// Helper function to set consumer config defaults from above.\nfunc setConsumerConfigDefaults(config *ConsumerConfig, streamCfg *StreamConfig, lim *JSLimitOpts, accLim *JetStreamAccountLimits, pedantic bool) *ApiError {\n\t// Setup default of -1, meaning no limit for MaxDeliver.\n\tif config.MaxDeliver == 0 || config.MaxDeliver < -1 {\n\t\tif pedantic && config.MaxDeliver < -1 {\n\t\t\treturn NewJSPedanticError(errors.New(\"max_deliver must be set to -1\"))\n\t\t}\n\t\tconfig.MaxDeliver = -1\n\t}\n\t// Setup zero defaults.\n\tif config.MaxWaiting < 0 {\n\t\tif pedantic {\n\t\t\treturn NewJSPedanticError(errors.New(\"max_waiting must not be negative\"))\n\t\t}\n\t\tconfig.MaxWaiting = 0\n\t}\n\tif config.MaxAckPending < -1 {\n\t\tif pedantic {\n\t\t\treturn NewJSPedanticError(errors.New(\"max_ack_pending must be set to -1\"))\n\t\t}\n\t\tconfig.MaxAckPending = -1\n\t}\n\tif config.MaxRequestBatch < 0 {\n\t\tif pedantic {\n\t\t\treturn NewJSPedanticError(errors.New(\"max_batch must not be negative\"))\n\t\t}\n\t\tconfig.MaxRequestBatch = 0\n\t}\n\tif config.MaxRequestExpires < 0 {\n\t\tif pedantic {\n\t\t\treturn NewJSPedanticError(errors.New(\"max_expires must not be negative\"))\n\t\t}\n\t\tconfig.MaxRequestExpires = 0\n\t}\n\tif config.MaxRequestMaxBytes < 0 {\n\t\tif pedantic {\n\t\t\treturn NewJSPedanticError(errors.New(\"max_bytes must not be negative\"))","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/consumer.go#L610-L646","documentation":"This is a JetStream consumer configuration validation error raised in pedantic mode when MaxAckPending is set below -1 (e.g. -5). Unlike other negative values that are silently clamped to 0 in non-pedantic mode, max_ack_pending has a special sentinel value of -1 meaning 'unlimited', so only -1 or non-negative values are valid. In pedantic mode the server rejects the config instead of silently fixing it.","triggerScenarios":"Creating or updating an ephemeral/durable pull consumer (ConsumerCreate/ConsumerUpdate or js.AddConsumer) with ConsumerConfig.MaxAckPending set to a negative value less than -1 while the request enables pedantic validation (Validate(pedantic=true) path in server/consumer.go:628).","commonSituations":"Developers intending 'unlimited' pending acks type -10, -100, or misuse a negative constant; config loaded from YAML/JSON where a sign typo slipped in; libraries wrapping the NATS API mapping -1 incorrectly plus an offset.","solutions":["Set MaxAckPending to -1 exactly to request unlimited pending acknowledgments.","Set MaxAckPending to a positive integer (e.g. 1000) or leave it 0 to use the server default/stream limit.","Search your config files/code for negative MaxAckPending assignments and fix the sign.","If you control the client, call config validation (Validate(true)) client-side before sending to catch this early."],"exampleFix":"// before\nnc, _ := nats.Connect(nats.DefaultURL)\njs, _ := nc.JetStream()\njs.AddConsumer(\"ORDERS\", &nats.ConsumerConfig{\n    Durable:       \"worker\",\n    MaxAckPending: -10, // invalid: only -1 means unlimited\n})\n// after\njs.AddConsumer(\"ORDERS\", &nats.ConsumerConfig{\n    Durable:       \"worker\",\n    MaxAckPending: -1, // unlimited\n})","handlingStrategy":"validation","validationCode":"func validMaxAckPending(v int) bool { return v >= 0 || v == -1 }\nif !validMaxAckPending(cfg.MaxAckPending) { return errors.New(\"max_ack_pending must be -1 or non-negative\") }","typeGuard":"func isUnlimitedAckPending(v int) bool { return v == -1 }","tryCatchPattern":"_, err := js.AddConsumer(\"ORDERS\", &cc)\nvar apiErr *nats.APIError\nif errors.As(err, &apiErr) && strings.Contains(apiErr.Description, \"max_ack_pending\") {\n    cc.MaxAckPending = -1\n    _, err = js.AddConsumer(\"ORDERS\", &cc)\n}","preventionTips":["Remember only -1 is the 'unlimited' sentinel for MaxAckPending; any other negative is invalid.","Validate consumer configs with config.Validate(true) before sending to the server.","Sanitize values loaded from YAML/JSON/CLI with a sign check on integer fields."],"tags":["jetstream","consumer-config","validation","nats"],"backgroundTag":"invalid-argument-value","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}