Mobile is not verified
Trigger
Authenticated user starts checkout before mobile verification.
System response
The create endpoint rejects the request with 403 before loading pricing or touching any slot claim.
Slot does not belong to the requested ground
Trigger
bookingSlotId is valid, but groundId in the request points to a different ground.
System response
The request is rejected with 400 so users cannot pay against a mismatched ground/slot pair.
Ground does not support requested sport
Trigger
sportId is not the primary sport and is not present in active ground sport configs.
System response
The request is rejected before pricing so the booking cannot store an invalid sport context.
Venue or ground is not bookable
Trigger
Ground is inactive, ground is under maintenance, venue is inactive, venue is under maintenance, or venue is tournament-only.
System response
Checkout stops with a 400 class error and no GroundBooking hold is created.
Slots are being regenerated
Trigger
Redis key lock:ground:slotregen:<groundId> exists while checkout starts.
System response
The system returns 409 because slot rows may be changing; if Redis check itself fails, the error is logged and checkout continues.
Slot starts too soon
Trigger
Slot is past, ongoing, within the 10 minute final booking buffer, or less than token expiry plus buffer away.
System response
The request is rejected because the user may not have enough time to complete Paytm payment safely.
Slot already final or blocked
Trigger
BookingSlot.status is Booked or Blocked before claim creation.
System response
The system returns 409 and never creates a Pending booking for that slot.
Pricing cannot be resolved
Trigger
Dynamic/static pricing rules cannot produce a valid payable amount for the sport, side count, turf mode, and time band.
System response
The endpoint returns 422 for pricing resolution errors before any hold is created.
Two users tap the same slot
Trigger
Both hit create booking while BookingSlot is Available.
System response
First request locks the slot row and creates the active hold. The second request sees the active hold or lock contention and receives 409.
Database row lock times out
Trigger
Another transaction is holding the BookingSlot row longer than the 3000ms lock timeout or a deadlock is detected.
System response
The error is normalized to 409: this slot is already being booked by another player.
Duplicate active holds already exist
Trigger
The locked slot query finds more than one Pending/Failed hold with holdExpiresAt in the future.
System response
The system logs a data-integrity event and rejects the slot as temporarily unavailable.
Other user active hold
Trigger
The only active hold belongs to another user.
System response
The current user gets 409 while the existing hold remains untouched until payment, failure, or expiry.
Same user taps pay again
Trigger
A Pending booking exists with active Paytm txnToken.
System response
If pricing context matches and provider status is not successful, the existing session is reused instead of creating duplicate orders.
Same user changes pricing criteria
Trigger
User retries the same slot with different sport, pricing rule, side count, turf mode, or base amount while the old hold is active.
System response
The system returns 409 and asks the user to wait for hold expiry instead of silently changing a live payment session.
Paytm says active order already succeeded
Trigger
The reuse check for an active pending order gets a provider success status.
System response
Create booking returns 409 telling the user to verify payment, preventing a duplicate retry order.
Active pending provider status fetch fails
Trigger
Paytm status lookup fails before deciding whether an expired active txnToken can be retried.
System response
If the token is expired, retry is blocked with 409 because the system cannot prove whether money was captured.
Payment token expired
Trigger
Same user returns after txnToken expiry.
System response
The system renews hold ownership under the row lock and creates the next Paytm attempt with a new order id.
Expired pending order may have succeeded
Trigger
Hold expired but Paytm order is still Pending locally.
System response
Before retry, the system fetches Paytm status. If success, it reconciles; if failure, it creates a retry; if unknown, it blocks retry.
Expired failed order retry
Trigger
Same user has no active hold, but has an expired Failed booking for the same slot and sport.
System response
The system renews the booking hold, mirrors Redis again, and creates the next Paytm attempt under the same booking id.
Active failed order retry
Trigger
The user's active hold is Failed, still within holdExpiresAt, and has Paytm order/token data.
System response
Provider status is checked; if it did not succeed, the hold is renewed and a new Paytm attempt is created.
Paytm initiation fails on fresh hold
Trigger
The DB hold and Redis mirror exist, but createPaytmTransaction throws before an attempt is persisted.
System response
The uninitialized GroundBooking is deleted and Redis hold is released only if the payload still belongs to that booking/user.
Paytm initiation fails on retry
Trigger
A retry hold was renewed, but the provider order creation fails.
System response
The system releases only the owned Redis mirror and keeps the historical booking record for audit.
Redis hold mirror fails
Trigger
redis.set for hold:slot:<slotId> fails after the durable DB hold was created or renewed.
System response
The failure is logged, but the database hold remains the source of truth for blocking checkout.
Verify order belongs to another user
Trigger
Client verify is called with an orderId linked to a different user.
System response
The endpoint returns 403 and does not expose booking or payment state.
Verify order id does not match booking id
Trigger
Manual/status endpoints receive a bookingId and orderId pair that do not match the booking record.
System response
The request is rejected with 400 so ops tools cannot mutate the wrong payment attempt.
Paytm returns non-final status
Trigger
Provider status is neither in success statuses nor failure statuses.
System response
Payment remains Pending; verify returns pending and create retry paths block until a final status is known.
Payment success after lost claim
Trigger
Paytm reports success but the order is superseded, hold expired, or slot is unavailable.
System response
Booking is cancelled with RefundPending so the slot is not double booked.
Old Paytm attempt succeeds after retry
Trigger
Webhook or verify succeeds for an order that is no longer the booking's current paytmOrderId or attempt number.
System response
The old attempt is marked RefundPending/Cancelled, but the latest booking claim is not overwritten.
Slot update loses the race
Trigger
Claim validation passed, but BookingSlot update where status Available affects zero rows.
System response
The booking is moved from Paid candidate state to RefundPending/Cancelled and the slot is not stolen.
Payment failure webhook
Trigger
Paytm webhook returns TXN_FAILURE, FAILURE, F, or NO_RECORD_FOUND for a Pending booking.
System response
The latest booking and payment attempt are updated to Failed/Cancelled with provider transaction metadata.
Webhook repeats or arrives after verify
Trigger
Paytm sends duplicate or late payment webhook.
System response
Idempotent update conditions and attempt history prevent a resolved booking from being incorrectly rewritten.
Payment webhook missing order id
Trigger
Paytm payment webhook does not include ORDERID.
System response
The webhook is logged and rejected with 400, because no booking can be safely identified.
Payment webhook checksum fails
Trigger
Key-value Paytm webhook signature verification fails.
System response
The webhook is rejected with 400 and no booking/payment state is changed.
Payment webhook has non-final status
Trigger
Webhook status is unknown or pending.
System response
The event is logged as ignored and the booking remains in its current state.
Refund requested after slot start
Trigger
Ops/user tries to refund a paid booking after the slot start time.
System response
Refund is rejected because only pre-start active bookings can be refunded through the normal paid-booking refund path.
Refund requested for non-paid booking
Trigger
Refund endpoint is called for a booking that is not Paid/Booked.
System response
Normal refund is rejected; only RefundInitiated, RefundPending, or RefundFailed cancelled bookings go through refund-pending processing.
Refund transaction id missing
Trigger
Booking has no paytmTxnId and Paytm status lookup cannot resolve one.
System response
Refund initiation is marked RefundFailed or rejected because Paytm requires a transaction id.
Refund provider returns failed status
Trigger
Paytm refund initiate/status returns a known failed status.
System response
The booking remains Cancelled and paymentStatus moves to RefundFailed for manual retry/support.
Refund webhook lacks order id
Trigger
Paytm refund webhook contains only refund reference.
System response
The system tries to recover the order from paytmRefundRefId or paytmRefundId before applying refund status.
Refund webhook checksum fails
Trigger
JSON or key-value refund webhook signature verification fails.
System response
The webhook is rejected with 400 and no refund state is changed.
Refund webhook only says accepted
Trigger
Webhook status maps to accepted/pending but not completed.
System response
The booking stays Cancelled and paymentStatus becomes RefundPending until status sync or a later webhook resolves it.
Refund completed later
Trigger
Refund status sync or webhook returns TXN_SUCCESS/SUCCESS/S.
System response
The booking remains Cancelled and paymentStatus becomes Refunded with refund id, provider status, and payload history stored.