Skip to content

Cancel a Search

A player backs out of matchmaking. You call CancelTicket. There is a race here, and you have to handle it.

sequenceDiagram
    autonumber
    actor P as Player
    participant GB as Your Backend
    participant IM as IVK Match

    P->>GB: cancel_matchmaking(ticket_id)
    GB->>IM: CancelTicket(queue_id, ticket_id)

    alt Ticket still waiting in the pool
        IM-->>GB: ok
        GB-->>P: cancelled
    else Ticket already committed to a match
        IM-->>GB: FAILED_PRECONDITION
        Note over GB: The match is already formed.<br/>Its outcome is in flight.
        GB-->>P: too late, match found
        IM->>GB: outcome: match.created
        GB->>GB: proceed with provisioning
    end

A failed cancel does not mean the player is still queued

Section titled “A failed cancel does not mean the player is still queued”

It usually means the opposite. FAILED_PRECONDITION means a match has already been committed and its outcome is on its way to you. Read it as “a match is coming, prepare to honour it”.

Get this one wrong and it hurts. Drop the match.created that follows a failed cancel and you strand every other player in that match: they get sent to a server one player never joins, or to a match that never starts.

So on FAILED_PRECONDITION:

  • Tell the player the search already succeeded, rather than that cancellation failed.
  • Keep handling the incoming match.created normally: provision, notify, and put that player in the match.
  • If your game genuinely must let the player out, do it after the match is honoured, and treat it as a leave rather than a cancel.

Cancelling an unknown queue_id returns FAILED_PRECONDITION rather than NOT_FOUND. Cancelling a ticket that has already expired or been removed is not an error worth surfacing to the player; they are already out of the pool either way.

See Matchmaking API § Cancel a ticket for the full contract.