Custom Post Type Loop throws 500 error when used in widget

There are several problems in your provided code.

$query -> while( have_posts() )

The WP_Query() return type is object. You are referring to a method that doesn’t exist. Instead, you should use the following:

while( $query->have_posts() ) {...}

wp_reset_postdata(); inside the conditional

This function resets the post’s data, as it suggests. If you use it inside a conditional, and the conditional doesn’t run, your post’s data won’t be reset, leaving an empty query active. So, you should use it outside the conditional, or before return, if you are returning the data instead.

the_... instead of get_the_...

If you want to store the data in a variable, you should use a function that returns the data, not echo it. the_post_thumbanil() echoes the thumbnail, while you need to return it. So, you should use get_the_post_thumbnail() instead. This applies to every WordPress function that begins with the_..., as far as i know.