The root of the problem is that you’re using s
, the post query search parameter, but the code is for a user query.
This means if your user query has 5 pages, but only 2 pages of posts are found, page 3 will 404.
Instead, use a dedicated parameter with $_GET
that isn’t a reserved query var already. This does mean the search.php
template won’t be used, but that can be fixed in many ways, e.g. a page template, rewrite rules, template filters, etc
A sidenote on performance
meta_query
has very poor performance. If the values you are searching for are not fuzzy, consider using user taxonomies to store them. This will provide a dramatic performance boost. Post/User/Term meta are optimised for get_post_meta
type calls where you already know the post ID, the tables are not structured in a way that makes searches/filtering/grouping posts by meta performant.
Keep this in mind as there is a tradeoff here, meta is fast in get_post_meta
type situations, and gets significantly slower at meta_query
type situations as the table increases in size. Taxonomies aren’t as fast for retrieval but they’re orders of magnitude faster than meta_query
type queries. This is why categories and tags aren’t stored in post meta, but stuff like the featured image ID are.