is_search was called incorrectly

The Why part

In the core is_search() function there’s a check if the global $wp_query is set:

global $wp_query;

if ( ! isset( $wp_query ) ) {
    _doing_it_wrong( __FUNCTION__, 
       __( 'Conditional query tags do not work before the query is run.
            Before then, they always return false.' ), '3.1.0' );
    return false;
}

Note that you’re unsetting it with:

$wp_query = null;

just before you create a new WP_Query subquery, that calls is_search() when pre_get_posts fires.

That’s when the _doing_it_wrong() is activated.

Workaround

Always try to use the main query, instead of extra WP_Query sub-queries if possible, to avoid running extra database queries.

To target the main search query in the front-end, we can use:

add_action('pre_get_posts', function( \WP_Query $q ) {
    if ( 
            ! is_admin()         // Only target the front-end
         && $q->is_main_query()  // Target the main query
         && $q->is_search()      // Target a search query
    ) {
        // do stuff
    }
});