get_posts() interrupt because of filter

Check that the current query is the main query using $query->is_main_query().

add_action( 'pre_get_posts', array($this, 'exclude_category') );

public function exclude_category( $query){    
    if( is_admin() && $query->is_main_query() && isset( $_GET['cta_filter']) && ! empty( $_GET['cta_filter'] ) ) {
        $term = sanitize_text_field( $_GET['cta_filter'] );

        $tax_query = $query->get('tax_query') ?: array();

        $tax_query[] = array(
            'taxonomy' => 'cta_tax',
            'field'    => 'slug',
            'terms'    => array( $term ),
            'operator' => 'IN'
        );

        $query->set('tax_query',$tax_query):
    }
}

I’m assuming ?cta_filter= is only going to be set on your post type’s admin page so no further conditions are necessary, but to be even safer you might want to add another condition:

&& 'post_type_name' === $query->get( 'post_type' )

Also note another change I made to your code. Rather than modifying query properties directly, I suggest using the get() and set() methods.