Sanity Studio image upload hanging on large JPG files

16 replies
Last updated: Mar 8, 2022
Hi folks! I’m having a lot of trouble uploading images in Sanity Studio, it just hangs for a super long time. The images I’m trying to upload aren’t anything special, generally around 1.5MB or smaller JPGs. Has anyone else experienced something like this? This isn’t self-hosted btw, it’s hosted on sanity.studio.
AI Update

I feel your pain! Image upload hanging issues in Sanity Studio can be really frustrating. Based on a similar issue from the Sanity community, the most likely culprit is actually in your image schema configuration.

The Main Issue: Invalid Metadata Options

If you have an image field with a metadata array in your schema, check if you're including dimensions, hasAlpha, or isOpaque. These options are not valid for the metadata array and will cause uploads to fail with a 400 error.

Here's what an incorrect schema looks like:

{
  name: 'myImage',
  type: 'image',
  options: {
    metadata: [
      'dimensions',    // ❌ Invalid
      'hasAlpha',      // ❌ Invalid  
      'isOpaque',      // ❌ Invalid
      'blurhash',      // ✅ Valid
      'lqip',          // ✅ Valid
      'palette',       // ✅ Valid
      'exif',          // ✅ Valid
    ],
  },
}

The Fix

Remove dimensions, hasAlpha, and isOpaque from your metadata array. The valid metadata options are:

  • blurhash
  • lqip
  • palette
  • exif
  • location

After updating your schema, restart your Studio dev server.

Other Troubleshooting Steps

If the schema fix doesn't solve it, try these:

  1. Check browser console - Open DevTools (F12) and look for errors in the Console and Network tabs during upload. A 400 error on the asset upload endpoint is a dead giveaway for the metadata issue.

  2. Try a different browser - Browser extensions (especially ad blockers or privacy tools) can interfere with uploads to Sanity's Asset CDN.

  3. Network issues - Corporate firewalls, VPNs, or restrictive network policies can block uploads to cdn.sanity.io.

  4. Clear browser cache - Sometimes cached authentication tokens cause problems.

If you need to clean up any partially uploaded assets that are stuck, you can use the Sanity CLI to delete assets with commands like sanity documents delete targeting sanity.imageAsset documents.

The metadata configuration issue was fixed in Sanity Studio v2.28.0, where invalid metadata options are now silently removed instead of causing upload failures. Make sure you're on the latest version!

Show original thread
16 replies
Hi Piper. I haven’t seen any signal of that lately. Is the studio version up-to-date? Are there any hints in your dev tools?
Thanks for the reply
user A
, sorry for my delay! Taking care of a sick kid while trying to work...
The studio version I’m using v2.27.2 so I think I’m up-to-date. It’s really strange... when I have a single image field in place, I can’t drag-to-upload or use the upload button. When I have an image field within an array (for a gallery sort of situation), I’m able to drag in to the array field to upload.

When the upload hangs, if I refresh the page, the image is basically half-uploaded with the SVG icon in place (no image preview). In the data returned by a groq query, it says that there is no asset for that image.

If I cancel the upload when it hangs, it cancels no problem.

I’m not seeing anything unusual in the console, no errors or anything.

Let me know if there is any other info I could provide!
Not a problem! Hope they’re feeling well soon.
Yes, you’re up-to-date. Do you get the same result in a different browser? What does the schema look like on the page in question?
Interesting! I was trying it in Chrome before. I tried it in Safari just now and instead of hanging, I got an error like “unable to upload at this time” (wasn’t able to take a screenshot because it was too quick).
Also, there are these errors in the console:


ResizeObserver loop completed with undelivered notifications.

[Error] Failed to load resource: the server responded with a status of 400 () (production, line 0)
<https://2g3wminh.api.sanity.io/v1/assets/images/production?tag=sanity.studio.asset.upload&filename=ephemera-sam-baldwin-180507-185944.jpeg&meta=dimensions&meta=hasAlpha&meta=isOpaque&meta=blurhash&meta=lqip&meta=palette&meta=exif>
And this warning:

The input component for type "item" has no associated ref element. Please check the implementation of "Unknown" [
Object
]. If this is a function component, it must be wrapped in React.forwardRef(). Read more at <https://docs.sanity.io/help/input-component-no-ref>
(editing that message, I sent it too soon)
This is the schema for the whole document, the field I’m experimenting with is `images`:

import { MdOutlineInsertDriveFile } from 'react-icons/md'

export default {
  name: 'item',
  title: 'Item',
  type: 'document',
  icon: MdOutlineInsertDriveFile,
  groups: [
    {
      name: 'data',
      title: 'Data'
    },
    {
      name: 'images',
      title: 'Images'
    },
  ],
  fieldsets: [
    {
      name: 'dimensions',
      title: 'Dimensions',
      options: {
        columns: 2,
      },
    }
  ],
  fields: [
    {
      name: 'title',
      type: 'string',
      validation: Rule => Rule.required(),
    },
    {
      name: 'slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
      },
      validation: Rule => Rule.required(),
    },
    {
      name: 'publishedAt',
      title: 'Published at',
      type: 'datetime',
      initialValue: (new Date()).toISOString(), // Set date automatically
      validation: Rule => Rule.required(),
    },
    {
      name: 'images',
      type: 'array',
      title: 'Images',
      of: [
        {
          name: 'image',
          type: 'singleImage',
        },
      ],
      options: {
        layout: 'grid',
      },
      validation: Rule => Rule.required(),
    },
    {
      name: 'designer',
      type: 'reference',
      weak: true,
      to: {type: 'designer'},
      group: 'data',
    },
    {
      name: 'tags',
      type: 'array',
      of: [
        {
          type: 'reference',
          weak: true,
          to: {type: 'tag'},
        },
      ],
      group: 'data',
    },
    {
      name: 'typefaces',
      type: 'array',
      of: [
        {
          type: 'reference',
          weak: true,
          to: {type: 'typeface'},
        },
      ],
      group: 'data',
    },
    {
      name: 'width',
      type: 'number',
      description: 'Width in millimetres',
      group: 'data',
      fieldset: 'dimensions',
    },
    {
      name: 'height',
      type: 'number',
      description: 'Height in millimetres',
      group: 'data',
      fieldset: 'dimensions',
    },
    {
      name: 'artworkDate',
      title: 'Artwork date',
      type: 'date',
      group: 'data',
    },
    {
      name: 'notes',
      type: 'blockContent',
      group: 'data',
    },
  ],

  preview: {
    select: {
      title: 'title',
      images: 'images',
    },
    prepare(selection) {
      const {title, images} = selection
      return {
        title: title,
        media: images ? images[0] : false,
      }
    }
  },

  orderings: [
    {
      title: 'Artwork Date, New',
      name: 'artworkDateDesc',
      by: [
        {field: 'artworkDate', direction: 'desc'}
      ]
    },
    {
      title: 'Artwork Date, Old',
      name: 'artworkDateAsc',
      by: [
        {field: 'artworkDate', direction: 'asc'}
      ]
    },
    {
      title: 'Published At, New',
      name: 'publishedAtDesc',
      by: [
        {field: 'publishedAt', direction: 'desc'}
      ]
    },
    {
      title: 'Published At, Old',
      name: 'publishedAtAsc',
      by: [
        {field: 'publishedAt', direction: 'asc'}
      ]
    },
  ]
}
Thanks for these details. What does
singleImage
look like?
Lol, I realized I missed sending that about 10 minutes ago and jumped on here to share it. Sorry! This is
singleImage


export default {
  name: 'singleImage',
  title: 'Image',
  type: 'image',
  fields: [
    {
      name: 'alt',
      title: 'Alt text',
      type: 'string'
    }
  ],
  options: {
    accept: 'image/*',
    metadata: [
      'dimensions',
      'hasAlpha',
      'isOpaque',
      'blurhash',
      'lqip',
      'palette',
      'exif',
    ],
  },
}
(Not sure if this is relevant, but the few uploads that I have had success with don’t seem to return anywhere near the amount of EXIF data that I would expect. Camera info, etc. is missing, the only included info is the pixel dimensions and maybe one other value IIRC)
Thanks Piper. That may turn out to be relevant, for sure. I’ll follow up with you tomorrow.
Thanks so much, I really appreciate it!
Hi
user A
, any chance you have more info about what might be going on? No worries at all if not yet, and pls don’t feel the need to reply on a weekend! Just wanted to ask since I had a chance to be on my computer for a moment.
Hi Piper. Thanks for your patience. Could you try removing
dimensions
,
hasAlpha
, and
isOpaque
from your
metadata
array? They aren’t valid values and I suspect they’re causing the problem. If that still doesn’t work after restarting your studio process, please let me know.
Interesting. This page says they can be defined. I’m checking to see if something changed and this page is now out-of-sync. In the meantime, I’d still encourage you to try removing them from your array to see if it helps.
v2.28.0 contains some improvements to how you experience the
metadata
array. If you specify any of those three strings in your array that previously threw an error, they will now be quietly removed. The docs have also been updated to better represent what the array expects. Hope this helps!
That’s great, thanks so much
user A
! I really appreciate it!

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?