voice-quickstart-ios: Getting Error: EndCallAction transaction request failed: The operation couldn’t be completed. (com.apple.CallKit.error.requesttransaction error 4.)

Hello Twilio Support,

I am using TwilioVoice 2.0.4 for VoIP calling in my application. I have taken the sample code from TwilioVoiceCallKitQuickStart project. But I’m facing a random issue with it.

When callInviteReceived is called with state == cancelled, and I try to end the call, the incoming call screen from CallKit does not go away and the phone continues to ring even when the call has been disconnected by the dialer.

I’m getting the below error logged on the console:

EndCallAction transaction request failed: The operation couldn’t be completed. (com.apple.CallKit.error.requesttransaction error 4.)

I searched for the possible causes of the error and found that it comes when the UUID used in CXEndCallAction does not correspond to a known call. But if that is the case, this error should be repeated all the time, but it only happens occasionally.

Please let me know what I’m doing wrong here.

    func callInviteReceived(_ callInvite: TVOCallInvite) {
        NSLog("callInviteReceived:")
        
        print("Call Invite UUID: ", callInvite.uuid)
        if (callInvite.state == .pending) {
            NSLog("state == received")
            handleCallInviteReceived(callInvite)
        } else if (callInvite.state == .canceled) {
            NSLog("state == cancelled")
            handleCallInviteCanceled(callInvite)
        }
    }
    
    func handleCallInviteReceived(_ callInvite: TVOCallInvite) {
        
        if (self.incomingCallInvite != nil && self.incomingCallInvite?.state == .pending) {
            NSLog("Already a pending incoming call invite.");
            NSLog("  >> Ignoring call from %@", callInvite.from);
            
            showMissedCallNotification(callInvite)
            
            return;
        } else if (self.call != nil) {
            NSLog("Already an active call.");
            NSLog("  >> Ignoring call from %@", callInvite.from);
            
            showMissedCallNotification(callInvite)
            
            return;
        }
        
        self.incomingCallInvite = callInvite
        

        print("Reporting incoming call for uuid: ",callInvite.uuid)
        self.reportIncomingCall(uuid: callInvite.uuid)
    }
    
    func handleCallInviteCanceled(_ callInvite: TVOCallInvite) {
        //Perform End Call action
        performEndCallAction(uuid: callInvite.uuid)

        if !incomingCallDetailFromServer.isEmpty {
            DatabaseManager.saveMissedCallInCoreData(number: callInvite.from, missedCallDetail: incomingCallDetailFromServer)
        }
            
        else {
            DatabaseManager.saveMissedCallInCoreData(number: callInvite.from, missedCallDetail: [:])
        }
        
        //Show missed call notification
        showMissedCallNotification(callInvite)
        
        //set call invite to nil
        self.incomingCallInvite = nil
        
        //dismiss the alert for incoming call
        self.dismissIncomingCallAlertDelegate?.dismissIncomingCallAlert()
    }

  func performEndCallAction(uuid: UUID) {
        
        let endCallAction = CXEndCallAction(call: uuid)
        let transaction = CXTransaction(action: endCallAction)
        
        print("PerformingEndCallAction for uuid: ",uuid)
        callKitCallController?.request(transaction) { error in
            if let error = error {
                NSLog("EndCallAction transaction request failed: \(error.localizedDescription).")
                return
            }
            
            NSLog("EndCallAction transaction request successful")
        }
    }

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 1
  • Comments: 23 (11 by maintainers)

Most upvoted comments

I having an issue with endCall on the receiver side. Updating from 2.0.0 beta to 2.5.3 resolved this issue for me.

EDIT: Nope. Facing the issue again. I checked the start and end call UUID, it is the same, yet it throws the error code 4. How~

EDIT: Okay, so after tinkering around, I found the issue was that, when disconnecting in didDisconnectWithError with an Error, in my case the room has already ended, I was calling the callKitCallController.request(CXEndCallAction) which gave me an error of com.apple.CallKit.error.requesttransaction error 4 at this point I just had to call

let reason = CXCallEndedReason.remoteEnded
self.callKitProvider.reportCall(with: uuid, endedAt: nil, reason: reason)

And it would disconnect without an issue. Hope this helps. Cheers! 👍

Hi @bchen-twilio

I am getting the issue when trying to disconnect the call from dialer end before the receiver has answered it. In this case call:didDisconnectWithError: is not called since there is no connected call.

I have also tried removing the line from call:didDisconnectWithError:. But I don’t think that it is disconnecting the call properly because when I try to make another call to the same number, the receiver’s screen show options: “Decline”, “End & Accept” but the second option should be “Accept” since the previous call has been disconnected.

Thanks