wpdb::prepare() isn’t working

The issue is that in My/SQL table names are not strings. So 'wp_product_codes' is being interpreted as a string instead of as an actual table. This is why you usually don’t see tables passed into wpdb::prepare() – you should know the table names as they won’t change where wpdb::prepare() is meant for data that you may not know / can’t be trusted and needs to be sanitized. So let’s modify the query:

$existing_data = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}product_codes" );
printf( '<pre>%1$s</pre>', print_r( $existing_data, 1 ) );
die();