instructure/canvas-lms · error · CalendarEvent::ReservationError
participant has met per-participant limit
Error message
participant has met per-participant limit
What it means
CalendarEvent.reserve_for raises ReservationError when the appointment group's max_appointments_per_participant is set and the participant already holds reservations equal to or exceeding that limit. It enforces the per-participant cap on an appointment group before creating a new reservation.
Solutions
- Cancel an existing reservation first (if it is in the future) so the count drops below the limit, then retry reserve_for.
- Raise max_appointments_per_participant on the appointment group via its update API if the limit is too strict.
- Check reservations_for(participant).size before calling and surface a friendly 'limit reached' UI message instead of attempting the booking.
Example fix
// before slot.reserve_for(user, participant, cancel_existing: true) // after limit = appointment_group.max_appointments_per_participant existing = appointment_group.reservations_for(participant) if limit && existing.size >= limit raise UserFacingError, 'You have reached the booking limit for this appointment group' end slot.reserve_for(user, participant)
Defensive patterns
Strategy: validation
Validate before calling
limit = appointment_group.max_appointments_per_participant if limit && appointment_group.reservations_for(participant).size >= limit raise UserFacingError, 'booking limit reached' end
Try / catch
begin
slot.reserve_for(user, participant)
rescue ReservationError => e
if e.message.include?('per-participant limit')
notify_limit_reached(participant)
else
raise
end
end Prevention
- Check reservation count against max_appointments_per_participant before booking
- Display remaining slots to the user in the scheduler UI
- Avoid retry loops around reserve_for without canceling reservations
When it happens
Trigger: Calling reserve_for when context.max_appointments_per_participant is non-nil and context.reservations_for(participant).size >= max_appointments_per_participant.
Common situations: Student booking more appointment-group slots than the course allows; integrations or scripts looping over multiple slots; users double-submitting the booking form.
Related errors
- cannot cancel past reservation
- all slots filled
- ineligible participant
- invalid participant
- not an appointment
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/bfea7ecaf6df5640.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/calendar_event.rb:608
def reserve_for(participant, user, options = {})
raise ReservationError, "not an appointment" unless context_type == "AppointmentGroup"
raise ReservationError, "ineligible participant" unless context.eligible_participant?(participant)
transaction do
lock! # in case two people two participants try to grab the same slot
participant.lock! # in case two people try to make a reservation for the same participant
if options[:cancel_existing]
context.reservations_for(participant).lock.each do |reservation|
raise ReservationError, "cannot cancel past reservation" if reservation.end_at < Time.now.utc
reservation.updating_user = user
reservation.destroy
end
end
raise ReservationError, "participant has met per-participant limit" if context.max_appointments_per_participant && context.reservations_for(participant).size >= context.max_appointments_per_participant
raise ReservationError, "all slots filled" if participants_per_appointment && child_events.size >= participants_per_appointment
raise ReservationError, "participant has already reserved this appointment" if child_events_for(participant).present?
event = child_events.build
event.updating_user = user
event.context = participant
event.workflow_state = :locked
event.comments = options[:comments]
event.save!
if active?
self.workflow_state = "locked"
save!
end
context.clear_cached_available_slots!
event
end
end
View on GitHub (pinned to 1c9f0bb801)