Pagination 404 on Index with custom query

whether or not a page exists or results in a 404 is decided based on the results of the main query, which happens before the template is loaded. WordPress isn’t “aware” of your custom query, it’s separate from the main query and happens only if the main query results in the loading of the template which contains it.

instead of creating this custom query, you can modify the main query before it is sent to the database via the pre_get_posts action. this code would go in your theme’s functions.php file:

function wpa_front_page_projects( $query ) {
    if ( $query->is_front_page() && $query->is_main_query() ) {
        $query->set( 'post_type', array( 'project' ) );
        $query->set( 'posts_per_page', 5 );
    }
}
add_action( 'pre_get_posts', 'wpa_front_page_projects' );