temporalio/temporal · error
expect at least one reservation
Error message
expect at least one reservation
What it means
NewMultiReservation wraps the results of reserving from multiple rate limiters. It panics when ok==true but the reservations slice is empty — an inconsistent state, since a successful multi-reservation must contain at least one underlying reservation.
Source
Thrown at common/quotas/multi_reservation_impl.go:21
import (
"time"
)
type (
MultiReservationImpl struct {
ok bool
reservations []Reservation
}
)
var _ Reservation = (*MultiReservationImpl)(nil)
func NewMultiReservation(
ok bool,
reservations []Reservation,
) *MultiReservationImpl {
if ok && len(reservations) == 0 {
panic("expect at least one reservation")
}
return &MultiReservationImpl{
ok: ok,
reservations: reservations,
}
}
// OK returns whether the limiter can provide the requested number of tokens
func (r *MultiReservationImpl) OK() bool {
return r.ok
}
// Cancel indicates that the reservation holder will not perform the reserved action
// and reverses the effects of this Reservation on the rate limit as much as possible
func (r *MultiReservationImpl) Cancel() {
r.CancelAt(time.Now())
}
View on GitHub (pinned to bde624efd1)
Solutions
- Only pass ok=true when at least one reservation was collected (len(reservations) > 0)
- Fix the underlying rate limiter that returns a successful reservation without a Reservation object
- If no limiters participated, pass ok=false instead
Example fix
// before res := quotas.NewMultiReservation(ok, collected) // after ok = ok && len(collected) > 0 res := quotas.NewMultiReservation(ok, collected)
Defensive patterns
Strategy: validation
Validate before calling
ok = ok && len(reservations) > 0 res := quotas.NewMultiReservation(ok, reservations)
Try / catch
func() (r quotas.Reservation) {
defer func() {
if recover() != nil { r = failedReservation }
}()
return quotas.NewMultiReservation(ok, reservations)
}() Prevention
- Only set ok=true when at least one reservation was collected
- Test custom RateLimiters return non-nil Reservation on success
- Treat an empty reservation list as a failed reserve
When it happens
Trigger: Calling NewMultiReservation(true, nil) or NewMultiReservation(true, []quotas.Reservation{}) — e.g. when Reserve loops over limiters but collects no reservations while still reporting ok.
Common situations: Buggy custom RateLimiter whose Reserve returns ok=true with a nil reservation; assembling reservations from a filtered list that dropped all entries.
Related errors
- expect at least one rate limiter
- expect at least one rate limiter
- Request to priority & priority to rate limiter does not matc
- Found key with non-zero pending task count but has no corres
- unknown workflow update abort reason %s or update state %s
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/5e0996ecb3a4286c.
Report an issue: GitHub.