{"record":{"id":"b55cc49be8a0ca0e","repo":"micro/go-micro","slug":"invalid-ackwait-passed-should-be-positive-integer","errorCode":null,"errorMessage":"invalid AckWait passed, should be positive integer","messagePattern":"invalid AckWait passed, should be positive integer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"events/memory.go","lineNumber":135,"sourceCode":"\t}\n\n\t// Note: RetryLimit is configured but retry logic is basic for the in-memory implementation.\n\t// For production use with advanced retry capabilities, use NATS JetStream.\n\n\t// setup the subscriber\n\tsub := &subscriber{\n\t\tChannel:    make(chan Event),\n\t\tTopic:      topic,\n\t\tGroup:      options.Group,\n\t\tretryMap:   map[string]int{},\n\t\tautoAck:    true,\n\t\tretryLimit: options.GetRetryLimit(),\n\t\tnotify:     make(chan struct{}, 1),\n\t}\n\n\tif !options.AutoAck {\n\t\tif options.AckWait == 0 {\n\t\t\treturn nil, fmt.Errorf(\"invalid AckWait passed, should be positive integer\")\n\t\t}\n\t\tsub.autoAck = options.AutoAck\n\t\tsub.ackWait = options.AckWait\n\t\tgo sub.dispatchManualAck()\n\t}\n\n\t// register the subscriber\n\tm.Lock()\n\tm.subs = append(m.subs, sub)\n\tm.Unlock()\n\n\t// lookup previous events if the start time option was passed\n\tif options.Offset.Unix() > 0 {\n\t\tgo m.lookupPreviousEvents(sub, options.Offset)\n\t}\n\n\t// return the channel\n\treturn sub.Channel, nil","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/events/memory.go#L117-L153","documentation":"The in-memory events implementation requires AckWait to be a positive duration when AutoAck is disabled, because the manual-ack dispatcher needs to know how long to wait before redelivering unacknowledged events. Consume rejects the subscription when AutoAck is false and AckWait is left at its zero value.","triggerScenarios":"Calling mem.Consume(topic, events.DisableAutoAck()) without events.AckWait(d) — options.AutoAck is false and options.AckWait == 0.","commonSituations":"Porting code from auto-ack to manual-ack consumption and forgetting the new required option; copying option lists where AckWait was removed; builders that set DisableAutoAck conditionally without setting AckWait alongside it.","solutions":["Pass events.AckWait with a positive duration alongside DisableAutoAck, e.g. events.AckWait(30*time.Second)","If you want default acking, drop DisableAutoAck so AutoAck stays true","Validate your option-builder logic so AckWait is always set when manual ack is enabled","For heavy manual-ack workloads consider NATS JetStream, which has richer ack policies"],"exampleFix":"// before\nevents.Consume(topic, events.DisableAutoAck()) // invalid AckWait\n// after\nevents.Consume(topic, events.DisableAutoAck(), events.AckWait(30*time.Second))","handlingStrategy":"validation","validationCode":"func consumeOpts(autoAck bool, ackWait time.Duration) ([]events.ConsumeOption, error) {\n    if !autoAck && ackWait <= 0 {\n        return nil, errors.New(\"AckWait must be positive when AutoAck is disabled\")\n    }\n    opts := []events.ConsumeOption{}\n    if !autoAck {\n        opts = append(opts, events.DisableAutoAck(), events.AckWait(ackWait))\n    }\n    return opts, nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Whenever you pass DisableAutoAck, always pass AckWait alongside it","Wrap option construction in a helper that enforces the pairing","Default AckWait to something sane (e.g. 30s) in your service config","Add a startup test that consumes with your production option set"],"tags":["events","ack","validation","configuration"],"backgroundTag":"invalid-ackwait-option","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}