My file reference metafield image won't show up on the product page — what am I missing?

A file_reference metafield is a pointer to a file, not the image itself — skip the .value step, or feed the wrong file type into image_url, and the picture never shows.

metafieldsmedialiquidfile_referencetheme development

What's going on

A merchant adds a file-type metafield to a product — for a spec sheet image, a size chart, or extra product artwork — and tries to display it on the product page template. Instead of the picture, the page shows a broken image icon, a blank space where the image should be, or a Liquid error in the theme editor pointing at image_url. Sometimes the raw value prints as text instead, something like a long gid://shopify/MediaImage/ string sitting right there on the page.

This happens because a file_reference metafield doesn't store an image URL directly. It stores a reference to a file object living in Shopify's Files system, and that object might be an image, a video, or a generic file depending on how the metafield definition was set up. Liquid needs an extra step to resolve that reference before any image filter can use it, and if that step is skipped, or the underlying file isn't actually an image, rendering breaks in one of several visible ways.

Why it happens

The image_url filter only produces useful output when it's given an actual image object — one with a width, height, and source. Calling it on the metafield itself, before pulling out the referenced file, returns nothing or throws an error, since the metafield wrapper isn't an image object.

A file_reference metafield's raw value in Liquid is the metafield wrapper, not the file. You have to call .value on it to get the underlying file object — for example product.metafields.custom.my_field.value — before any image filter can act on it.

The metafield definition's validation determines what .value actually resolves to. If the definition allows any file type, an image upload can still come back looking like a generic file object without image properties, and a genuinely non-image file will never render as a picture no matter what Liquid syntax is used.

5 ways to fix it

1

Resolve the reference with .value, then let image_url and image_tag do the work

In Liquid, a file_reference metafield is a pointer, not an image — you have to unwrap it first: assign img = product.metafields.custom.spec_sheet.value, then render it with img | image_url: width: 1200 | image_tag: loading: 'lazy', alt: img.alt. Calling image_url directly on the metafield instead of on img.value is the single most common cause of a blank box or a Liquid error, since the filter needs an actual image object (with width, height, and a source) to work from, not the metafield wrapper around it. Passing a width also keeps the file from loading at a much larger size than the page actually needs.

2

Check whether the metafield definition actually restricts uploads to images

In Settings, under Custom data, open the metafield definition attached to this field and check its validation. A generic file reference field accepts any upload — PDFs, videos, spec documents — and a non-image file resolves in Liquid to an object with no width, height, or image source, so image_url will fail or render nothing even though something is attached. If this field is meant to always hold a picture, tighten the definition's file type validation to images only, or create a separate image-only metafield dedicated to artwork so Liquid consistently gets back an object it can size and render.

3

If the field holds multiple files, loop over the list instead of treating it as one object

A list-type file reference metafield resolves through .value to an array, not a single file. Piping that array straight into image_url is a common source of a silent failure or a template error. Use a for loop to iterate over the array and call image_url on each file inside the loop instead.

4

If you just need the image to show up, try a metafield block in the theme editor first

On an Online Store 2.0 theme, you often don't need to hand-write any Liquid for a straightforward case like this. Add a metafield-type block to the product section in the theme editor and point it at the file reference field — the built-in block handles resolving the reference and sizing the image for you, which sidesteps syntax mistakes entirely when custom layout isn't required.

5

For recurring image-driven fields like swatches, weigh custom Liquid against dedicated tooling

If the underlying goal is something bigger, such as color or variant swatches built from image metafields across a large catalog, hand-rolled Liquid per section starts to get fragile and hard to maintain. At that scale it's worth comparing a theme section built specifically for metafield-driven swatches against maintaining custom snippets yourself, since the ongoing upkeep is often the real cost, not the initial syntax.

Bottom line

This is fixable with plain Liquid in almost every case — the fix is nearly always resolving .value first, checking that the metafield definition's file type matches what's actually stored, and adjusting for list versus single-file fields. Reach for a theme block before writing custom Liquid if the display need is simple, and only consider a dedicated app if you're building something more elaborate, like a swatch system driven by image metafields across many products.

Still Stuck?

Browse the rest of the problem library, run a free storefront scan to catch issues like this automatically, or email us and we'll work out a custom solution for it.