Show taxonomy term meta field on single template

Your code doesn’t show where $term_id is coming from. If it is not defined anywhere, then that could be causing the problem.

Instead of using get_term() and get_term_meta() directly on your template file, you could define couple of helper functions to handle the data retrieval. This makes the template file a little cleaner and the code reusable should you need the same data elsewhere.

For example you could do something like this.

// functions.php helpers
function my_post_experts(int $post_id): array {
    $terms = get_the_terms( $post_id, 'expert' );

    return is_array($terms) ? array_map('my_wp_term_to_expert', $terms) : [];
}

function my_wp_term_to_expert(WP_Term $term): array {
    $imge = get_term_meta($term->term_id, 'tax_img', true);
    
    return [
        'name' => $term->name,
        'img_url' => $imge ?: '',
    ];
}

// single template
$experts = my_post_experts(get_the_ID());
if ($experts) {
    foreach ($experts as $expert) {
        printf(
            '<div class="tnl-expert">
                <h4>Expert: %s</h4>
                <div class="tnl-expert-img">
                    <img src="%s">
                </div>
            </div>',
            esc_html($expert['name']),
            esc_url($expert['img_url'])
        );
    }
}