How to limit WP_Query to one result on the loop?

pre_get_posts alters all queries, back end and front end regardless.

There are two very important checks that a large amount of people misses, that is the !is_admin() check which only targets the front end, and then the most important check, is_main_query() which will only alter the main query and not custom queries.

You statement should look something like the follwoing

if (    !is_admin() 
     && $query->is_main_query()  
     && $query->is_search()  
) {
    // Your arguments to set
}

tech