SIP Protocols & StandardsKnowledge baseIETF Standards ยท RFC 3261

SIP CANCEL vs. BYE Workflows: Handling Race Conditions and Call Teardown Edge Cases

by Provider Adminlast verified 2026-08-04

Overview

Understanding the core differences between SIP CANCEL and BYE requests is crucial for building resilient VoIP networks. While CANCEL targets an in-flight INVITE transaction before final response, BYE terminates an established early or confirmed dialog. This guide covers transaction-level mechanics, common race conditions defined in RFC 5407, parallel forking behaviors, and proper handling of teardown edge cases in Proxies and B2BUAs.

Illustration for SIP CANCEL vs. BYE Workflows: Handling Race Conditions and Call Teardown Edge Cases

Key takeaways

  • CANCEL is a hop-by-hop transaction request targeting an uncompleted INVITE, whereas BYE is an end-to-end dialog request targeting an established session.
  • A CANCEL request has no effect on an INVITE transaction that has already received a final 2xx response.
  • When a 200 OK to INVITE crosses a CANCEL in transit, the caller must acknowledge the 200 OK with an ACK and then immediately send a BYE to tear down the dialog.
  • Proxies handling parallel forking must automatically issue CANCEL requests to all pending branches once a 2xx response is received from any single branch.
  • B2BUAs must maintain accurate dialog and transaction state machines to avoid leaving orphan RTP streams or stuck channels during teardown races.

Prerequisites

  • Basic knowledge of RFC 3261 SIP transaction and dialog state machines.
  • Understanding of SIP response codes (1xx provisional, 2xx success, 4xx client failure).
  • Familiarity with SIP header fields including Call-ID, From, To, CSeq, and Via.

Guide

  1. section #1

    Architectural Differences: CANCEL vs. BYE In Session Initiation Protocol (SIP), CANCEL and BYE serve fundamental yet distinct roles in session teardown. CANCEL is a transaction-level request used to abort a pending INVITE request that has not yet received a final response (2xx-6xx). Because CANCEL acts on an uncompleted transaction, it operates hop-by-hop; each proxy along the signaling path processes the CANCEL and generates its own response to that request before forwarding it downstream. Conversely, BYE is a dialog-level request used to terminate an established session (either an early dialog or a confirmed dialog). BYE operates end-to-end, traveling along the route set established during dialog formation.

    text
    CANCEL Scope: Transaction-level (Hop-by-Hop)
    [UAC] --- INVITE ---> [Proxy] --- INVITE ---> [UAS]
    [UAC] --- CANCEL ---> [Proxy] --- CANCEL ---> [UAS]
    
    BYE Scope: Dialog-level (End-to-End Route Set)
    [UAC] <================ Dialog Established ================> [UAS]
    [UAC] --------------------- BYE --------------------------> [UAS]
  2. section #2

    Mechanics of the CANCEL Transaction A CANCEL request must match the INVITE transaction it intends to cancel. To achieve this, the CANCEL request is constructed with matching Call-ID, To, From (including tags), and CSeq numeric values as the original INVITE. However, the method in the CSeq header must be CANCEL. The Via header top element must match the branch parameter of the top Via in the INVITE request for that hop. Upon receiving a valid CANCEL, a UAS or proxy returns a 200 OK to the CANCEL transaction itself and immediately responds to the pending INVITE transaction with a 487 Request Terminated response, which the UAC acknowledges with an ACK.

    http
    INVITE sip:bob@example.com SIP/2.0
    Via: SIP/2.0/UDP client.example.com:5060;branch=z9hG4bK776asdhds
    Max-Forwards: 70
    From: Alice <sip:alice@example.com>;tag=1928301774
    To: Bob <sip:bob@example.com>
    Call-ID: a84b4c76e66710@client.example.com
    CSeq: 314159 INVITE
    
    CANCEL sip:bob@example.com SIP/2.0
    Via: SIP/2.0/UDP client.example.com:5060;branch=z9hG4bK776asdhds
    Max-Forwards: 70
    From: Alice <sip:alice@example.com>;tag=1928301774
    To: Bob <sip:bob@example.com>
    Call-ID: a84b4c76e66710@client.example.com
    CSeq: 314159 CANCEL
  3. section #3

    The 200 OK vs. CANCEL Race Condition (RFC 5407 Section 3.1.1) A classic SIP race condition occurs when the caller (UAC) decides to cancel a call at the exact moment the callee (UAS) answers it. The UAC transmits a CANCEL request while the UAS simultaneously transmits a 200 OK (INVITE). Because the packets cross on the network, the UAS receives the CANCEL after it has already sent its 200 OK. According to RFC 3261, a CANCEL has no effect on an INVITE transaction that has already completed with a 2xx response. The UAS responds to the CANCEL with a 200 OK (or 481 Call/Transaction Does Not Exist), but the primary INVITE transaction concludes successfully. The UAC receives the 200 OK (INVITE), creating a confirmed dialog. To resolve this without leaving an orphaned call, the UAC MUST complete the 3-way handshake by sending an ACK, and then immediately send a BYE request to terminate the established dialog.

    text
    UAC                                           UAS
     |                                             |
     |--- INVITE --------------------------------->|
     |<-- 180 Ringing -----------------------------|
     |                                             |
     | (User hangs up)         (User answers)      |
     |--- CANCEL -------------\ /------------------- 200 OK (INVITE)
     |                        X                    |
     |<----------------------/ \------------------>|
     |
     |--- 200 OK (CANCEL) ------------------------>| (UAS acknowledges CANCEL)
     |--- ACK ------------------------------------>| (UAC must ACK 200 OK)
     |--- BYE ------------------------------------>| (UAC immediately tears down)
     |<-- 200 OK (BYE) ----------------------------|
    
  4. section #4

    Early Dialogs and Provisional Responses When an INVITE receives a provisional response containing a To tag (such as 180 Ringing or 183 Session Progress), an early dialog is established. If a caller cancels the call during this phase, standard practice dictates sending a CANCEL request to terminate the INVITE transaction. The UAS responds with 200 OK to the CANCEL and 487 Request Terminated to the INVITE, which implicitly destroys the early dialog. Sending a BYE within an early dialog is syntactically permitted by RFC 3261 under specific constraints, but many legacy stacks fail to handle early BYE correctly. Therefore, using CANCEL during early dialogs remains the RFC-compliant best practice.

  5. section #5

    Forking Proxies and Multibranch CANCEL Propagation When a stateful SIP proxy performs parallel forking, it sends the initial INVITE to multiple destinations simultaneously. If one branch responds with a 200 OK, the proxy immediately forwards the 200 OK upstream to the UAC and must automatically generate a CANCEL request for all other active branches. If the caller hangs up before any branch answers, the proxy receives a CANCEL from the UAC, generates a 200 OK (CANCEL) back to the UAC, and replicates the CANCEL to every downstream branch that has sent a 1xx provisional response. Branches that have not yet sent any provisional response must be tracked so that a CANCEL can be dispatched as soon as a 1xx response arrives, or the transaction must be cancelled locally.

    text
    UAC                 Stateful Proxy               Target A            Target B
     |--- INVITE -------------->|                       |                   |
     |                          |--- INVITE ----------->|                   |
     |                          |--- INVITE ------------------------------->|
     |                          |<-- 180 Ringing -------|                   |
     |                          |<-- 180 Ringing ---------------------------|
     |--- CANCEL -------------->|                       |                   |
     |<-- 200 OK (CANCEL) ------|                       |                   |
     |                          |--- CANCEL ----------->|                   |
     |                          |--- CANCEL ------------------------------->|
     |                          |<-- 200 OK (CANCEL) ---|                   |
     |                          |<-- 200 OK (CANCEL) -----------------------|
     |                          |<-- 487 Terminated ----|                   |
     |                          |<-- 487 Terminated ------------------------|
    
  6. section #6

    B2BUA and Session Border Controller Teardown Best Practices Back-to-Back User Agents (B2BUAs) and SBCs manage two distinct SIP dialogs (leg A and leg B). When implementing call teardown logic on a B2BUA, developers must strictly decouple transaction handling from media session controls to prevent hung channels or leaks. When a CANCEL is received on Leg A, the B2BUA must check the state of Leg B. If Leg B has not yet received a 2xx final response, the B2BUA issues a CANCEL on Leg B. If Leg B has already received a 200 OK (INVITE) due to network race conditions, the B2BUA must issue an ACK followed by a BYE on Leg B, while completing the 487/ACK sequence on Leg A. Furthermore, RTP ports and hardware media channels should only be released after the final ACK or 200 OK (BYE) exchange completes, or when Timer H/Timer J expires.

Further reading

  • RFC 3261: SIP - Session Initiation Protocol (Section 9: Canceling a Request, Section 15: Terminating a Session)
  • RFC 5407: Session Initiation Protocol (SIP) Small-Time Race Conditions Example Call Flows
  • RFC 3326: The Reason Header Field for Session Initiation Protocol (SIP)