When get_field() returns nothing in WordPress, the issue is almost always one of eight things. I have debugged this exact symptom hundreds of times over fifteen years of agency work. Here is the order I check, with the fix for each.
Jump to:
- Cause 1: Field name typo
- Cause 2: Wrong post ID / context
- Cause 3: Field group location rules do not match
- Cause 4: Field group exists but is not assigned
- Cause 5: Trying to read a sub-field with get_field()
- Cause 6: get_field() vs the_field() confusion
- Cause 7: Object cache returning stale data
- Cause 8: Field type returning a different shape than expected
- The diagnostic order
Cause 1: Field name typo
The most common cause. ACF field names are case-sensitive, snake_case by convention, and easy to mistype.
// Field is registered as "hero_heading" but called as:
$heading = get_field( 'heroheading' ); // returns null
$heading = get_field( 'Hero_Heading' ); // returns null
$heading = get_field( 'hero-heading' ); // returns nullFix: confirm the exact field name by exporting the field group (Custom Fields > Tools > Export Field Groups) and reading the JSON, or by inspecting the field group in the admin UI. The name is the lowercase, underscore-separated identifier.
Cause 2: Wrong post ID / context
get_field() defaults to the current post in the loop. If you call it outside the loop, on a different post type, or on an options page without telling it, you get nothing.
// Outside the loop or in the wrong context
$value = get_field( 'hero_heading' ); // unsure which post
// Explicit post ID, always safer
$value = get_field( 'hero_heading', 123 );
$value = get_field( 'hero_heading', $post->ID );
$value = get_field( 'hero_heading', 'option' ); // options page
$value = get_field( 'hero_heading', 'user_42' ); // user meta
$value = get_field( 'hero_heading', 'term_5' ); // taxonomy metaFix: always pass the second argument when you are not certain the function is being called inside the_loop().
Cause 3: Field group location rules do not match
ACF field groups have location rules ("show this field group if post type is X and post template is Y"). If the rules do not match the post you are reading, the field does not exist for that post and get_field() returns nothing.
Fix: open the field group in Custom Fields admin, scroll to "Location", confirm the rules match the post you are working with. A common mistake is restricting a field group to a specific page template, then assigning that template only to some pages but trying to read the field on other pages.
Cause 4: Field group exists but is not assigned
This is a flavor of Cause 3 that catches people moving sites between environments. The field group registration exists in the database on environment A but was not exported and imported into environment B. The code calls get_field() and gets nothing because the field group does not exist in the new environment at all.
Fix: confirm field groups exist on the target environment. wp acf list (with the ACF WP-CLI add-on) or a check via the admin UI both work. If they are missing, export from the source environment as JSON and either import via the admin or commit the JSON to the theme's acf-json/ directory for automatic sync.
Cause 5: Trying to read a sub-field with get_field()
get_field() reads top-level fields. Sub-fields inside a Repeater, Flexible Content, or Group field require get_sub_field() and must be called inside a have_rows() loop.
// Broken: get_field doesn't reach into sub-fields
$heading = get_field( 'stat_row_heading' );
// Correct: sub-fields inside have_rows
if ( have_rows( 'stat_rows' ) ) {
while ( have_rows( 'stat_rows' ) ) {
the_row();
$heading = get_sub_field( 'heading' );
}
}For deeper context on Flexible Content specifically, see ACF Flexible Content Loop Not Working? Here's the Fix.
Cause 6: get_field() vs the_field() confusion
get_field() returns the value. the_field() echoes it. If you wrote the_field() and assigned the result to a variable, the variable is null (because the_field() returns nothing) but the value got echoed to the page somewhere unexpected.
// Wrong
$heading = the_field( 'hero_heading' ); // $heading is null, echo happens
// Right
$heading = get_field( 'hero_heading' );
echo esc_html( $heading );This is a quick visual check: if the field value is appearing somewhere on the page you did not expect, you used the_field() by accident.
Cause 7: Object cache returning stale data
If the site is on a persistent object cache (Redis, Memcached) and an ACF field was just updated programmatically (via update_field() or wp acf update), the next get_field() call may return the cached old value rather than the new one.
Fix: clear the relevant cache key, or flush the object cache (wp cache flush) on the staging environment to confirm. On production, prefer targeted invalidation: wp_cache_delete( "post_meta:$post_id", 'options' ); for post meta, with similar patterns for other contexts.
This is rare in practice but it bites at exactly the wrong moment (right after a deploy when you cannot figure out why the value did not change).
Cause 8: Field type returning a different shape than expected
get_field() returns different shapes depending on the field type:
| Field type | Returns |
|---|---|
| Text, textarea, number | string |
| Image | array (URL, sizes, alt, etc.) or URL or ID, depending on return-format setting |
| File | array, URL, or ID |
| Gallery | array of image arrays |
| Relationship | array of post objects |
| Post Object | post object |
| User | user object array |
| Taxonomy | term object or array of term objects |
| True/False | boolean |
| Checkbox | array of selected values |
| Select | string or array depending on multiple-select setting |
| Date | string in the field's format |
| Repeater | array of arrays (or false if empty) |
| Flexible Content | array of arrays with layout key |
If you expected a string and got an array (very common with Image fields), get_field() is "returning nothing" only in the sense that the data is not the shape your code expected. For the image case specifically, ACF Image Field Returning an Array Instead of a URL? covers the return-format options.
The diagnostic order
When get_field() is returning nothing in production code:
var_dump( get_field( 'your_field_name', get_the_ID() ) )to see what you actually get.- Confirm the field name is exactly right (case, underscores).
- Confirm the post ID is correct for the context.
- Confirm the field group's location rules match the post.
- Confirm the field group exists at all on this environment.
- If reading a sub-field, switch to
get_sub_field()insidehave_rows(). - If on a cached environment, flush the cache to rule out staleness.
- If you get back data but in an unexpected shape, check the return-format setting in the field group admin.
In my experience, causes 1, 2, and 3 cover roughly 70% of cases. Cause 5 (sub-field confusion) covers another 15%. The remaining 15% is spread across the others.
For AI-assisted debugging of this kind of issue (where the assistant reads the field group registration and your template code, then diagnoses the mismatch), see Using Claude CLI to Manage WordPress Sites.
Sources
Authoritative references this article was fact-checked against.
- get_field() function reference (Advanced Custom Fields docs)advancedcustomfields.com
- the_field() function reference (Advanced Custom Fields docs)advancedcustomfields.com





