Discussion on resolving an error with image URLs in a Next.js app using @sanity/image-url library.

32 replies
Last updated: Aug 24, 2022
Hello, how can I solve this problem?

Unable to resolve image URL from source

Error: Unable to resolve image URL from source ([{"_key""image","asset""image-85fd403b1036fb99e0d0523eac35798f28d51dc5-828x1472-jpg","_type":"reference"}}])
AI Update

This error occurs when you're trying to generate an image URL using the @sanity/image-url library, but the data structure being passed doesn't match what the library expects. Based on the error message showing an array structure, here are the most common causes and solutions:

1. Passing an array instead of the image object

Your error shows the image data wrapped in square brackets [{...}], indicating it's an array. The urlFor() function expects an object, not an array:

// ❌ Wrong - passing an array
urlFor([imageData])

// ✅ Correct - passing the object directly  
urlFor(imageData)

2. Image field is defined as an array in your schema

If your image field is actually an array type in your Sanity schema, you need to access a specific image from that array or map through it:

// If image is an array, access the first image
urlFor(product.image[0])

// Or map through all images
{product?.image?.map(img => (
  <img key={img._key} src={urlFor(img).url()} />
))}

3. Not expanding the asset reference in your GROQ query

According to the Sanity documentation on presenting images, you need to expand the asset reference in your query:

// ❌ Wrong - doesn't expand the reference
*[_type == "post"] {
  title,
  image
}

// ✅ Correct - expands the asset reference
*[_type == "post"] {
  title,
  image {
    asset->
  }
}

4. Handling undefined values

Always check that the image data exists before trying to generate a URL:

{product.image?.asset && (
  <img src={urlFor(product.image).url()} alt={product.title} />
)}

Expected data structure

The @sanity/image-url library expects an object with an asset property containing either a reference or the full asset object:

// With reference
{
  asset: {
    _ref: "image-85fd403b...",
    _type: "reference"
  }
}

// Or with expanded reference (using asset-> in query)
{
  asset: {
    _id: "image-85fd403b...",
    url: "...",
    // other asset properties
  }
}

Based on a community discussion that resolved this exact issue, the most common solution is:

  1. Update your GROQ query to properly expand the asset reference using asset->
  2. If your image field is an array, map through it properly with a return statement
  3. Ensure you're not accidentally wrapping the image data in an array or passing undefined values to urlFor()

The working code pattern looks like this:

{products?.map(product => (
  <div key={product._id}>
    <h1>{product?.title}</h1>
    {product?.image?.map(image => (
      <img key={image._key} src={urlFor(image).url()} alt="" />
    ))}
  </div>
))}
{ "name": "my-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@sanity/client": "^3.3.3",
"@sanity/image-url": "^1.0.1",
"next": "12.2.5",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"eslint": "8.22.0",
"eslint-config-next": "12.2.5"
}
}
It looks like you're passing an entire block, not just the image asset. Can you try doing
product.image.asset
?
For some reason it seems to me that this is a problem of the updated react/next
Can you use optional chaining? It likely isn't defined yet if it's relying on an external call.
no, it's not about optional chaining, I'm sure. Its about library and React/Next. I'm not the only one with this problem
No, if you look at your data, your image field is actually an array of images, not an object. Dot notation won't work for accessing the asset.
You'll need to map through that array as well.
but I have 1 image and in tutorial it is working, lol
how can I loop?
You can map through an array.
I know, but how to do it with those images? I just don't get it. I'm trying, but nothing happens
product.image.map()
will iterate through your array of images. Then you'll need to return an image component for each image.
I've even tried [0] before
I'd suggest rereading carefully through your code. You're not returning anything from your image map. This reproduction works for me:
      {products?.map(product => (
        <div key={product._id}>
          <h1>{product?.title}</h1>
          {product?.image?.map(image => (
            <img src={urlFor(image).url()} />
          ))}
        </div>
      ))}
Oh, yeah. Thanks!
You are welcome! It's always a little thing like that.
https://i.imgur.com/b26F2Vf.png
I've just uploaded 1 more picture and I'm getting 2 arrays instead of 1.
even without that closure
If your client has a token, you're likely also getting the draft version of the document. It looks like you haven't published the changes in the Studio.
omg, you are right
thank you so much!!
You're very welcome 🙂

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?