Images are randomly deleted from server

Obviously, I imagine you already checked cron jobs.

No one can tell you, but whenever you have an issue and you’re wondering “what the hell is interacting with my system?” and that part that’s problematic (in your case, the deletion of the image) has actions inside of it, we can see what called that specific deletion. So let’s see how this applies in your case.

An image is a post. When it gets deleted, unless something bad happens, you can safely say that wp_delete_post will be used and inside of this function, we have the earliest action we can hook into before_delete_post:

add_action( 'before_delete_post', function( $postid ) {
    $past_backtrace = get_option( 'backtrace_for_deletion', [] );
    $current_backtrace = debug_backtrace();

    $past_backtrace[] = json_encode( $current_backtrace );
    update_option( 'backtrace_for_deletion', $past_backtrace );
});

We basically want to see what called this deletion, so let’s make it a bit prettier:

    $backtraces = get_option( 'backtrace_for_deletion' );
    foreach( $backtraces as $backtrace ) {
        ?>
        <pre>
        <?php
            print_r( json_decode( $backtrace ) );
            echo '-----------------------------------------------------------------------------------';
        ?>
        </pre>
        <?php
    }

This isn’t exactly the best view, but it gives you the information.

A few points:

  1. Third item is always where the deletion is called from, it’ll give you the exact file name and line of what called the deletion.
  2. If this doesn’t work, then I advise you turn server file logging on, as well as database logging and look at the queries.