Category template with pagination returns 404 on next pages

The steps WordPress takes to serve a front end request are roughly-

  1. The incoming URL is parsed and converted to query vars.

  2. These query vars form the Main Query, which is sent to the database.

  3. WordPress looks at the results and determines if the request was successful or not, which determines what status header to send- 200 OK, or 404 not found.

  4. WordPress loads the template that corresponds to this type of request, for example, a category archive template in the case of your category request, or the 404 template, in the case the main query has no posts.

So the shortest answer to your question as to why you are seeing a 404, is that the main query has no posts.

The query you run in the template and whatever pagination it generates is irrelevant to the main query. This is why you need to alter the main query with pre_get_posts to customize the results of an archive page.

If you just want pages, you can set post type to just page:

add_action( 'pre_get_posts', function($q) {
    if( !is_admin() && $q->is_main_query() && !$q->is_tax() ) {
        $q->set ('post_type', array( 'page' ) );
    }
});