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.
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)
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
- ai model is nil
- ErrMissingTopic
- no service name configured
- addr (nats subject) must not be empty
- flow: step %q 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.