ERROR · 48 · VERIFIED 2026-10allwpcare.com/errors/warning-attempt-to-read-property-on-null/
Errors / warning-attempt-to-read-property-on-null

Warning: Attempt to Read Property on Null

A theme or plugin read a property of a missing post, user or term. The path names who wrote it. Update or replace it, or check the value before reading it.

The message you see
1−Warning: Attempt to read property "ID" on null in /var/www/html/wp-content/themes/my-theme/footer.php on line 2
Last verified Oct 2026Tested with WordPress 7.1Applies to WordPress 7.1 (tested) · PHP 8.0+

Why it happens

  • A theme or plugin reads a property, such as $post->ID, from a value that is empty. On a 404 page or an empty search, WordPress has no current post, so the global $post is null.
  • A WordPress function found nothing and returned null or false. get_post(), get_page_by_path() and get_term() return null. get_user_by(), get_userdata() and get_term_by() return false. The code never checks.
  • The host moved the site to PHP 8.0 or newer. PHP 7.4 reported the same mistake as a notice, which WordPress hides when WP_DEBUG is off. PHP 8 reports it as a warning.
  • The server shows errors on the page (display_errors is on), or WP_DEBUG and WP_DEBUG_DISPLAY are on, so a message that used to stay in a log now reaches visitors.

How to fix it

Try the fixes in this order. Each one is independent: stop as soon as the error is gone.

FIX 01

Read the path to find who owns the code

  1. Look at the folder after wp-content/. themes/my-theme/ is a theme, plugins/name/ is a plugin, and mu-plugins/ holds must-use plugins that cannot be deactivated from the Plugins screen. A path in wp-includes/ or wp-admin/ would be WordPress core.
  2. The property name in quotes ("ID" above) and the line number are for the author. You do not need to open the file.
  3. Note which pages show it. If it only appears on 404 pages or empty search results, the code assumes a post that is not there.
FIX 02

Update, or replace, the theme or plugin

  1. Go to Dashboard → Updates and update the theme or plugin named in the path. A new version usually checks the value first.
  2. If there is no update, send the author the exact message and tell them which page shows it. A report that says "on a 404 page" is easy to act on.
  3. If it is no longer maintained, pick a replacement. A warning is not urgent, but code that was never updated for PHP 8 may have bigger problems.
  4. To check that it is the source, deactivate the plugin (Plugins → Installed Plugins → Deactivate, or wp plugin deactivate demo-bug) or switch theme (Appearance → Themes). On my test site the message was gone on the 404 page after each of these.
FIX 03

Stop visitors from seeing it: log, do not display

  1. In wp-config.php, above the line "That's all, stop editing", set define( 'WP_DEBUG', true );, define( 'WP_DEBUG_DISPLAY', false ); and define( 'WP_DEBUG_LOG', true );. The warning then goes to wp-content/debug.log and not onto the page. I tested this: the 404 page was clean and the log held one line.
  2. Turning WP_DEBUG off is not enough if your host has display_errors on. I tested that: with WP_DEBUG off and the server's display_errors on, the warning was still on the page. Ask the host to turn display_errors off.
  3. This hides the message. The code still has the bug. Turn WP_DEBUG off again when you are done and keep debug.log private (the WordPress site check tests whether it can be downloaded). See the WordPress debug log guide.
FIX 04

If you wrote the code: check the value first

  1. For the global post, test the type: if ( $post instanceof WP_Post ) { echo $post->ID; }. I used this in footer.php: the post page printed its ID, and the 404 and the empty search printed "none" with no warning.
  2. To get the ID of the current post, call get_the_ID() and test the result: $id = get_the_ID(); if ( $id ) { ... }. WordPress returns false when there is no post. For the page being viewed, get_queried_object_id() returns 0 instead of failing.
  3. isset( $post->ID ) also works and prints nothing for null, false or a missing property.
  4. On PHP 8.0 and newer, $post?->ID returns null instead of warning. It does not work on PHP 7.4 (a parse error) and it does not help when the value is false: get_user_by( 'login', 'nobody' )?->ID still warned. Check false with if ( $user ).
  5. Do not put @ in front of the line or lower error_reporting. Both leave the bug in place.

The message means that some code tried to read a property, such as $post->ID, from something that holds nothing. It is a warning, not a fatal error: PHP carries on, the page loads, and the value comes out empty. The path in the message names the theme or plugin that wrote the code. The usual trigger is a page with no post, such as a 404 or an empty search, where the code assumed there was one. The fix belongs to the author, so update or replace it. You can stop visitors seeing the message by writing errors to a log instead of the page.

What you see#

The message is plain text with no styling. PHP prints it where the code runs, so it often lands in the footer or at the top of the page.

A plain WordPress page titled My Test Site that says Nothing found. Below a grey line, in the footer: Footer for post Warning: Attempt to read property ID on null in /var/www/html/wp-content/themes/my-theme/footer.php on line 2.
A 404 page on WordPress 7.1.4 and PHP 8.3 with WP_DEBUG and WP_DEBUG_DISPLAY on. The page is complete and the status code is 404, as it should be. The footer shows the message where the ID should be.

I made it with a small classic theme. This is its whole footer.php:

wp-content/themes/my-theme/footer.php
<footer><p>Footer for post <?php echo $post->ID; ?></p><?php wp_footer(); ?></footer></body></html>

I loaded four URLs with the same theme:

Output
/hello-test/   [200] Footer for post 4/              [200] Footer for post 1/?s=zzz        [200] Footer for post  Warning: Attempt to read property "ID" on null in /var/www/html/wp-content/themes/my-theme/footer.php on line 2/nope-404/     [404] Footer for post  Warning: Attempt to read property "ID" on null in /var/www/html/wp-content/themes/my-theme/footer.php on line 2

The message shows on the pages that have no post. The page with a post is fine, and so is the home page. That is why theme authors miss it: it only shows on the pages they did not test.

How it works#

PHP does not complain when you ask an object for a property. It complains when the thing is not an object. null and false are not objects, so null->ID has nothing to read. PHP 8 says so with a warning and gives null for the result.

Four stacked cards. 1: the template line echo $post->ID. 2A: on a single post or a list with posts, WordPress found posts, $post holds a post object and the output is 4. 2B: on a 404 or an empty search the query found nothing, $post is null, and PHP prints Warning: Attempt to read property ID on null. 3: the fix is to check that $post is a WP_Post before reading it.
The same line of code gives a number on one page and a warning on another. What changes is whether WordPress found a post.

WordPress sets the global $post when it starts to build a page. In WP::register_globals() the line is $GLOBALS['post'] = $wp_query->post ?? null;. The query's first result goes in, and if the query found nothing, null goes in. A 404 and a search with no results have no posts, so $post is null on both.

The silent version of the same mistake#

When there are posts, $post is set but not always to the post you want. On the home page, the footer of my classic theme printed 1, which is the last post in the list. A block theme I tested the same code with printed 7, the first. Both are real posts, so no warning appears, and the code uses the wrong ID. Code that needs the post being viewed should check is_singular() first.

Where null and false come from#

The message ends in the type of the value. I called each of these on the lab site with a missing item and tried to read a property from the result:

CallReturnsMessage
get_post( 999999 )nullAttempt to read property "post_title" on null
get_page_by_path( 'nope' )null... "ID" on null
get_queried_object() on a page with no queried objectnull... "ID" on null
get_term( 999999, 'category' )null... "name" on null
global $post before WordPress has set itnot set... "ID" on null
get_user_by( 'login', 'nobody' )falseAttempt to read property "ID" on false
get_userdata( 9999 )false... "user_email" on false
get_term_by( 'slug', 'nope', 'category' )false... "name" on false
wp_get_attachment_metadata( 999 )false... "file" on false
get_option( 'missing' )false... "foo" on false
get_post_meta( 4, 'missing', true )empty string... "foo" on string
get_posts(...)[0] with no resultsno itemUndefined array key 0, then ... "ID" on null

Searches for "attempt to read property on bool" are the same problem. PHP 8.0 wrote bool where PHP 8.3 writes false. get_the_ID() does not fail like these. Its code is return ! empty( $post ) ? $post->ID : false;, so it gives false when there is no post.

What PHP 7.4 said#

The same mistake had a different message on the old PHP. I ran one file on three PHP versions:

t.php
$a = null; $b = false; $c = "str";echo $a->ID, $b->ID, $c->ID;
PHPMessage for null, false and a string
7.4Notice: Trying to get property 'ID' of non-object
8.0Warning: Attempt to read property "ID" on null (and on bool, on string)
8.3Warning: Attempt to read property "ID" on null (and on false, on string)

PHP's 8.0 notes list "attempting to read a property of a non-object" as a notice that became a warning. So code that ran quietly for years starts to talk after a PHP upgrade. Search for "trying to get property of non-object" and you will find the PHP 7 form of this page.

Why you may see it only sometimes#

PHP raises the warning. Whether it reaches the page depends on settings. I tested each on the 404 page:

WP_DEBUGWP_DEBUG_DISPLAYWP_DEBUG_LOGHost display_errorsResult
offn/an/aoffNothing on the page
offn/an/aonOn the page
ononanyanyOn the page
onoffonoffNot on the page. One line in wp-content/debug.log
wp-content/debug.log
[30-Oct-2026 12:02:52 UTC] PHP Warning:  Attempt to read property "ID" on null in /var/www/html/wp-content/themes/my-theme/footer.php on line 2

Unlike a deprecation, a warning is not dropped when WP_DEBUG is off. If the host shows errors, visitors see it. For the array version of the same idea, see the undefined array key page. For a property that was never declared, see the dynamic property page.

Each developer fix, tested#

I put each fix in place of the broken line and loaded a post, the home page, an empty search and a 404:

CodePostEmpty search and 404
if ( $post instanceof WP_Post )IDNothing, no warning
$id = get_the_ID(); if ( $id )IDNothing, no warning
isset( $post->ID )IDNothing, no warning
get_queried_object_id()ID0 on all three, no warning
$post?->IDIDEmpty, no warning
$user?->ID when $user is falsen/aWarning, "on false"
if ( $user ) before $user->IDn/aNo warning

The nullsafe operator only short-circuits on null, as PHP's manual says. It is fine for a value that may be missing. It is the wrong tool for functions that return false.

If the page goes blank#

A warning never stops a page by itself. A blank page or a critical error message is a different problem: see the white screen of death.

Sources

  1. PHP manual: Backward incompatible changes in PHP 8.0 · Attempting to read a property of a non-object changed from a notice to a warning.
  2. PHP RFC: Reclassifying engine warnings · The row "Trying to get property of non-object" moved from Notice to Warning, in the vote that passed 54 to 3.
  3. PHP manual: Classes and objects, nullsafe methods and properties · The ?-> operator, PHP 8.0 and later, returns null only when the object is null.
  4. WordPress reference: get_post() · Returns null on failure, and falls back to the global post when no ID is given.
  5. WordPress core: WP::register_globals() in wp-includes/class-wp.php · Sets the global post to the query's first post, or null when there is none.
Newsletter

One email when something breaks or changes.

New plugins and re-tested guides, about twice a month. Never a sales pitch.