Shopify Metafield Not Showing in Liquid: Fixed

You set a metafield in the admin, referenced it in Liquid, and the page renders nothing.
No error, no warning — just an empty space. Liquid fails silently on missing values, which makes this frustrating to debug. There are four causes and a fast way to tell them apart.
Symptom
{{ product.metafields.custom.care_instructions }}outputs nothing.- The value is clearly populated in Settings → Custom data.
- It may work in the theme editor preview but not on the live storefront.
- Or it renders as
ProductMetafield/[object Object]instead of the value.
Cause
1. Namespace or key mismatch
The reference must match exactly, including case. A definition in namespace custom with key care_instructions is not reachable as custom.careInstructions or Custom.care_instructions.
2. Storefront access is off
Metafields created via the Admin API, or older definitions, may not be exposed to the storefront. Liquid cannot read them until they are.
3. Wrong output syntax for the type
Since metafields became typed objects, the correct output depends on the type. Printing the object itself gives you the object, not the value.
4. Reading from the wrong owner
Product metafields are not variant metafields. product.metafields will never contain something set on a variant, a collection or the shop.
Fix
Step 1 — dump what actually exists
Before guessing, print everything:
{%- comment -%} Temporary debug block — remove before release. {%- endcomment -%}
<pre style="white-space:pre-wrap">
{%- for field in product.metafields.custom -%}
{{ field[0] }} = {{ field[1] }} (type: {{ field[1].type }})
{% endfor -%}
</pre>
To sweep every namespace:
{%- for ns in product.metafields -%}
<strong>{{ ns[0] }}</strong>
{%- for field in ns[1] -%}
<div>{{ ns[0] }}.{{ field[0] }} — {{ field[1].type }}</div>
{%- endfor -%}
{%- endfor -%}
If your field is absent entirely, it is cause 2 or 4. If it is present, it is cause 1 or 3.
Step 2 — enable storefront access
Settings → Custom data → Products → your definition → confirm Storefronts access is enabled. For API-created metafields, set it explicitly:
mutation {
metafieldDefinitionUpdate(definition: {
namespace: "custom"
key: "care_instructions"
ownerType: PRODUCT
access: { storefront: PUBLIC_READ }
}) {
updatedDefinition { id }
userErrors { field message }
}
}
Step 3 — output correctly for the type
{%- comment -%} single_line_text_field / multi_line_text_field {%- endcomment -%}
{{ product.metafields.custom.care_instructions.value }}
{%- comment -%} rich_text_field — metafield_tag renders the HTML {%- endcomment -%}
{{ product.metafields.custom.description | metafield_tag }}
{%- comment -%} file_reference — .value is the file object {%- endcomment -%}
{%- assign guide = product.metafields.custom.size_guide.value -%}
{%- if guide -%}
<img src="{{ guide | image_url: width: 800 }}" alt="Size guide" width="800" height="600">
{%- endif -%}
{%- comment -%} list.* — .value is an array {%- endcomment -%}
{%- for feature in product.metafields.custom.features.value -%}
<li>{{ feature }}</li>
{%- endfor -%}
{%- comment -%} product_reference {%- endcomment -%}
{%- assign related = product.metafields.custom.pairs_with.value -%}
{%- if related -%}
<a href="{{ related.url }}">{{ related.title }}</a>
{%- endif -%}
The rule: .value for almost everything, | metafield_tag for rich text.
Step 4 — guard against missing values
Metafields are frequently unset on some products. Always check before rendering surrounding markup:
{%- assign care = product.metafields.custom.care_instructions.value -%}
{%- if care != blank -%}
<div class="product-care">
<h3>Care instructions</h3>
{{ care }}
</div>
{%- endif -%}
Without the guard you ship an empty heading on every product that lacks the field.
Verify
- Load a product with the metafield set — value renders.
- Load one without it — no empty heading, no broken markup.
- View source on the live storefront, not just the theme editor preview.
- Remove the debug block.
Prevent
- Define metafields in the admin, not ad hoc via API, so storefront access and type are explicit.
- Keep a naming convention — lowercase with underscores, one namespace per concern.
- Always wrap in a
!= blankcheck. - Document which templates use which metafields, so a definition is never deleted while still referenced.
Frequently asked questions
Why does it work in the theme editor but not live?
Usually an unpublished definition change, or the editor previewing a different product. Always confirm against the live URL.
Can I read another product's metafields?
Yes, via a product_reference metafield or by looking the product up in all_products, but each lookup costs render time. Avoid it inside large loops.
What is the difference between .value and printing the metafield directly?
Printing the metafield gives you the object. .value gives the typed content. Older themes predate typed metafields, which is why tutorials disagree.
Related reading
- Liquid error: unknown tag "schema"
- Section schema will not save
- custom Shopify blocks — our service page
Need a hand?
We build Shopify themes that use custom data properly, for merchants in the USA, UAE, Saudi Arabia, Qatar and the UK. If metafields are not behaving, get a free audit or see our Shopify development work.
The Yaxify Team
Shopify & Web Development Agency
We build custom Shopify stores and high-performance websites for growing businesses across the USA, UK, and UAE. Everything we publish comes out of client work we have actually shipped.
More about Yaxify →