micro/go-micro · error
invalid AckWait passed, should be positive integer
Error message
invalid AckWait passed, should be positive integer
What it means
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.
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
Example fix
// before events.Consume(topic, events.DisableAutoAck()) // invalid AckWait // after events.Consume(topic, events.DisableAutoAck(), events.AckWait(30*time.Second))
Defensive patterns
Strategy: validation
Validate before calling
func consumeOpts(autoAck bool, ackWait time.Duration) ([]events.ConsumeOption, error) {
if !autoAck && ackWait <= 0 {
return nil, errors.New("AckWait must be positive when AutoAck is disabled")
}
opts := []events.ConsumeOption{}
if !autoAck {
opts = append(opts, events.DisableAutoAck(), events.AckWait(ackWait))
}
return opts, nil
} Prevention
- 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
When it happens
Trigger: Calling mem.Consume(topic, events.DisableAutoAck()) without events.AckWait(d) — options.AutoAck is false and options.AckWait == 0.
Common situations: 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.
Related errors
- addr (nats subject) must not be empty
- ai model is nil
- ErrMissingTopic
- flow: step has an empty name
- flow: step has no Run function
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/b55cc49be8a0ca0e.
Report an issue: GitHub.
Appendix: source
Thrown at events/memory.go:135
}
// Note: RetryLimit is configured but retry logic is basic for the in-memory implementation.
// For production use with advanced retry capabilities, use NATS JetStream.
// setup the subscriber
sub := &subscriber{
Channel: make(chan Event),
Topic: topic,
Group: options.Group,
retryMap: map[string]int{},
autoAck: true,
retryLimit: options.GetRetryLimit(),
notify: make(chan struct{}, 1),
}
if !options.AutoAck {
if options.AckWait == 0 {
return nil, fmt.Errorf("invalid AckWait passed, should be positive integer")
}
sub.autoAck = options.AutoAck
sub.ackWait = options.AckWait
go sub.dispatchManualAck()
}
// register the subscriber
m.Lock()
m.subs = append(m.subs, sub)
m.Unlock()
// lookup previous events if the start time option was passed
if options.Offset.Unix() > 0 {
go m.lookupPreviousEvents(sub, options.Offset)
}
// return the channel
return sub.Channel, nilView on GitHub (pinned to 24529f1404)