MetaMask internal JSON-rpc error when calling smart contract

Hi there,

We are building a escrow service on ethereum, and more specifically its about escrow on ERC20 tokens. First it deposits funds into a smart contract, and then release funds from the smart contract.

The problem happens when I do two escrows in a row, and the depositing part are all working fine. However, when I tried to invoke the MetaMask to call the smart contract to do two release funds in a row, got this rpc error.

The smart contract code is as like this:

function releaseEscrow(uint _orderId) external onlySeller(_orderId){ 
         Escrow memory _escrow = escrows[_orderId];     
        require(escrows[_orderId].status == EscrowStatus.Funded,"USDT has not been deposited");         
        _escrow.status = EscrowStatus.TokenApproved;
        uint256 _totalFees = _escrow.sellerfee + _escrow.buyerfee + _escrow.additionalGasFees;
        feesAvailable += _totalFees;
        // here we tell the curreny that the buyer can ONLY have 'value' funds.
        tokenccy.safeApprove(_escrow.buyer,(_escrow.value - _totalFees));
        require(_escrow.status == EscrowStatus.TokenApproved,"USDT has not been approved!");
        _escrow.status = EscrowStatus.Completed;
        tokenccy.safeTransfer( _escrow.buyer, (_escrow.value - _totalFees) );
        delete escrows[_orderId];
        emit EscrowComplete(_orderId, _escrow);

The actual deposit solidy code is as following:

function createEscrow(uint _orderId, address payable _buyer, address payable _seller, uint _value, uint _sellerfee, uint _buyerfee) external onlyOwner {
        require(escrows[_orderId].status == EscrowStatus.Unknown, "Escrow already exists");
        //Transfer USDT to contract after escrow creation
        require( tokenccy.allowance( _seller, address(this)) >= (_value),"Seller needs to approve funds to Escrow first !!");
        tokenccy.safeTransferFrom(_seller, address(this) , (_value) );
        Escrow memory _escrow =  Escrow(_buyer, _seller, _value, /*gas*/0, _sellerfee, _buyerfee, EscrowStatus.Unknown); 
         _escrow.status = EscrowStatus.Funded;
        escrows[_orderId] = _escrow;
        tokenccy.safeApprove(_escrow.buyer,0); // reset any allowances

        emit EscrowDeposit(_orderId, _escrow);

Could someone point me to the right direction?

Do we need to safeApprove each transaction before transfer?

Thanks in advance.