On mainnet unexpected InsufficientAllowance

Hey team.
This code works well for CLI and local deploy. But for mainnet I receive unexpected InsufficientAllowance for canister DFINITY Canister Candid UI

           valueFinal = await agentMotodex.value_in_main_coin(parseInt(args[0]))

            // Call the icrc2_approve() function
            approveArgs = {
                fee: [],
                memo: [],
                from_subaccount: [],
                created_at_time: [],
                amount: valueFinal,
                expected_allowance: [],
                expires_at: [],
                spender: {
                    owner: motoDEXprincipal, //i also tried the canisterId of the canister i launched
                    subaccount: [],

            icrc2_approve = await agentICP.icrc2_approve(approveArgs);
            console.log(" icrc2_approve " + JSON.stringify(stringFrom(icrc2_approve)))
            if (icrc2_approve.Ok) {
                console.log('Approve successful, transaction ID:', icrc2_approve.Ok);
                const purchase = await agentMotodex.purchase(parseInt(args[0]));
                if (purchase.Ok) {
                    console.log('purchase successful, token ID:', purchase.Ok);
                    response = [purchase.Ok + '',"done"];
                } else {
                    console.error('purchase failed:', purchase.Err);
                    response = "fail";

            } else {
                console.error('Approve failed:', icrc2_approve.Err);
                response = "fail";


In rust is its:

let price_for_type = value_in_main_coin(type_nft);
ic_cdk::print(format!("price_for_type {}", price_for_type));

let transfer_result = transfer_coin_to_owner(price_for_type);

and async fn transfer_coin_to_owner:

 async fn transfer_coin_to_owner(amount: u64) -> Result<BlockIndex, String> {

let transfer_result = transfer_coin_to_owner(price_for_type);

     async fn transfer_coin_to_owner(amount: u64) -> Result<BlockIndex, String> {
   let owner = STATE.with(|s| s.borrow_mut().contract.get_game_server());

let to_principal = owner.owner;
ic_cdk::print(format!("to_principal: {}", to_principal));

ic_cdk::print(format!("amount {}", amount));

let caller_acc = Account::from(ic_cdk::caller());
ic_cdk::print(format!("caller_acc {}", caller_acc));

    "Transferring {} tokens from {} to {}",

let transfer_from_args = TransferFromArgs {
    from: caller_acc,
    to: Account::from(to_principal),
    amount: amount.into(),
    fee: None,
    memo: None,
    spender_subaccount: None,
    created_at_time: None,
// Attempt the asynchronous call to another canister function.
let transfer_result =
    ic_cdk::call::<(TransferFromArgs,), (Result<BlockIndex, TransferFromError>,)>(
            .expect("Could not decode the principal."),
        .map_err(|e| format!("failed to call ledger: {:?}", e))?

// Check the result of the transfer.
match transfer_result {
    Ok(block_index) => {
        // If the transfer was successful, execute the additional code.

        ic_cdk::print(format!("transfer successful in block {}", block_index));
    Err(e) => {
        // If there was an error with the transfer, handle it accordingly.
        // For example, you might log the error or return it.
        Err(format!("ledger transfer error: {:?}", e))


How much do you attempt to transfer and how much do you approve for? And IIRC the error also reports what your actual allowance is. What does that say? AFAIU if you approve X and then try to transfer X this will fail because you need to be approved for X + transfer fee

Same as value_in_main_coin shown in canister UI
For example for type 0 its 71:
purchase failed: ledger transfer error: “ledger transfer error: InsufficientAllowance { allowance: Nat(71) }”

please check updated code

The solution is to either approve X + transfer fee or try to transfer X - transfer fee