pre_get_posts returns non property object when using posts__not_in

You are using pre_get_posts incorrectly.

  1. You should not be returning anything at all
  2. And you should be manipulating the query object that is passed into the filter and not modifying the globals at all.

For example:

function modify_onthisday_cat( $query ) {
  if ($query->is_category(7) && $query->is_main_query() ) {
    global $post; // not going to be set yet
    $query->set( 'day', date('d') );
    $query->set( 'post__not_in', array($post->ID) ); // and this will fail
  }
}
add_action( 'pre_get_posts', 'modify_onthisday_cat');

As noted in a comment, though, this won’t work for the main query (and you seem to intend it for such), since $post won’t be populated until after the main query runs– that is what determines the value(s) in $post. I think you are going to have to explain your goal in more detail.

Something like the following should work better for single post pages, at least.

function modify_onthisday_cat( $query ) {
  $post_id = get_query_var('p');
  if ($query->is_category(7) && $query->is_main_query() && !empty($post_id)) {
    $query->set( 'day', date('d') );
    $query->set( 'post__not_in', array($post_id) );
  }
}
add_action( 'pre_get_posts', 'modify_onthisday_cat');