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, nil

View on GitHub (pinned to 24529f1404)

Solutions

  1. Pass events.AckWait with a positive duration alongside DisableAutoAck, e.g. events.AckWait(30*time.Second)
  2. If you want default acking, drop DisableAutoAck so AutoAck stays true
  3. Validate your option-builder logic so AckWait is always set when manual ack is enabled
  4. 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

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-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/b55cc49be8a0ca0e. Report an issue: GitHub.