How can I show the error message only one time?

I am using PHP and JavaScript code on my WooCommerce website to display inline error messages on the wooocommerce checkout page.

Currently, the error message appears multiple times when any required field is empty due to a loop in the code. When I move the error handling code outside the loop, the message displays only once, but then the system does not redirect me to the payment page. I would like to show the error validation message “O o o p s, looks like some info is missing. Please fill in all *Required fields so we can complete your order” only once to ensure that I can still be redirected to the payment page.

PHP code:

add_action( 'woocommerce_after_checkout_form', 'add_custom_validation_script', 20 );

function add_custom_validation_script() {
    wp_enqueue_script(
        'inline_validation_script',
        get_stylesheet_directory_uri() . '/js/inline-validation.js',
        ['jquery']
    );
}

/**
 * adds error message field element to get inline error messages working
 * 
 * @param array $fields
 * @param object $errors
 */
add_filter( 'woocommerce_form_field', 'add_inline_error_messages_element', 10, 4 );

function add_inline_error_messages_element( $field, $key, $args, $value ) {
    if ( strpos( $field, '</span>' ) !== false ) {
        $error = '<span class="js-custom-error-message" style="display:none"></span>';
        $field = substr_replace( $field, $error, strpos( $field, '</span>' ), 0);
    }
    return $field;
}

/**
 * process custom checkout validations
 *
 * @param array $fields
 * @param object $errors
 */

add_action('woocommerce_after_checkout_validation', 'custom_checkout_validations', 10, 2);

function custom_checkout_validations($data, $errors){
    
    $your_custom_checkout_field = filter_input(INPUT_POST, 'your_custom_input_field');
    
    // your custom validations goes here
    // this loop adds a data array to all error messages which will be applied as a "data-error-for" HTML attribute
    // to read out the corresponding field ids with javascript and display the error messages inline
    foreach( $errors->errors as $original_key => $error ) {
        $field_key = $original_key;

        // filter and rewrite the field id for native woocommerce error messages with a key containing _required
        if(strpos($original_key, '_required') !== false) {
            $field_key = str_replace('_required','', $original_key);
            $error[0] = __('This is a required field', 'YourThemeName');
            
            if( !empty($errors->get_error_codes() ) ) {
                $errors->add( 'validation', 'O o o p s, looks like some info is missing. Please fill in all *Required fields so we can complete your order.' );
            }
        }
        
        // switch out the old error messages with the ones including a spiced up data array
        // to display with javascript
       $errors->remove($original_key);
       $errors->add($original_key, trim($error[0]), ['error-for' => $field_key . '_field']);
    }
}

JS code:

jQuery(function ($) {
    'use strict';

    addInlineMessages();

    // Implementation

    // Listen to js event
    $(document.body).on('updated_checkout', function() {
        addInlineMessages();
    });

    function addInlineMessages() {
        var woocommerceErrorsEl = $('.woocommerce-error');
        var woocommerceInlineErrorsEl = $('li[data-error-for]', woocommerceErrorsEl);
        var inlineErrorMessagesEl = $('.js-custom-error-message');

        // as we use ajax submitting hide old validation messages
        if(inlineErrorMessagesEl.length) {
            inlineErrorMessagesEl.hide();
        }

        if(woocommerceInlineErrorsEl.length) {
            woocommerceInlineErrorsEl.each(function () {
                var errorEl = $(this);
                var errorText = $.trim(errorEl.text());

                var targetFieldId = errorEl.data('error-for');

                if(errorText && targetFieldId) {
                    var targetFieldEl = $('#' + targetFieldId);
                    var errorMessageField = $('.js-custom-error-message', targetFieldEl);

                    if(targetFieldEl.length && errorMessageField.length) {
                        targetFieldEl.addClass('woocommerce-invalid');

                        errorMessageField.text(errorText);
                        errorMessageField.show();
                        errorEl.hide();
                    }
                }
            });

            if(woocommerceInlineErrorsEl.filter(':visible').length === 0) { 
                if(inlineErrorMessagesEl.filter(':visible').length > 0) {
                    scrollToElement(inlineErrorMessagesEl.filter(':visible').first());
                }
            } else {
                $('li:not([data-error-for])', woocommerceErrorsEl).hide();;
                scrollToElement(woocommerceErrorsEl);
            }
        }
    }

    function scrollToElement(el) {
        if(el.length) {
            $([document.documentElement, document.body]).animate({
                scrollTop: el.offset().top - 100
            }, 2000);
        }
    }

    // event listeners
    $(document.body).on('checkout_error', function (event) {
        jQuery('html, body').stop();

        addInlineMessages();
    });
});