Regression in Sanity 3.65.0 impacts array fields, update fixes

24 replies
Last updated: Jan 15, 2025
Can anyone help with this? I’m not sure what has caused this to happen, but the Array field is unusable for me and my client. Seems to be something with one of the packages rather than my preview config.
Here’s my preview config:


          preview: {
            select: {
              media: 'asset',
              caption: 'caption',
            },
            prepare({ media, caption }) {
              const title = caption ? toPlainText(caption) : 'Image'
              return {
                title,
                media,
              }
            }
          },
And here’s `package.json`:


{
  "name": "sanity-template-template-nextjs-personal-website",
  "private": true,
  "scripts": {
    "build": "next build",
    "dev": "next",
    "format": "npx prettier --write . --ignore-path .gitignore",
    "lint": "next lint -- --ignore-path .gitignore",
    "lint:fix": "npm run format && npm run lint -- --fix",
    "start": "next start",
    "type-check": "tsc --noEmit",
    "update-sanity-doc": "node updateSanityDocument.js"
  },
  "prettier": {
    "semi": false,
    "singleQuote": true
  },
  "dependencies": {
    "@hookform/resolvers": "^3.3.4",
    "@mux/mux-video-react": "^0.12.0",
    "@portabletext/react": "3.0.4",
    "@sanity/image-url": "1.0.2",
    "@sanity/preview-url-secret": "1.5.2",
    "@sanity/react-loader": "^1.7.4",
    "@sanity/vision": "3.25.0",
    "@tailwindcss/typography": "0.5.10",
    "@types/gtag.js": "^0.0.18",
    "a11y-react-emoji": "^1.2.0",
    "axios": "^1.6.5",
    "classnames": "2.3.2",
    "cookies-next": "^4.1.0",
    "date-fns": "2.30.0",
    "framer-motion": "^11.0.3",
    "lazysizes": "^5.3.2",
    "lottie-react": "^2.4.0",
    "next": "^14.0.4-canary.26",
    "next-sanity": "8.1.3",
    "react": "^18.3.0",
    "react-dom": "18.2.0",
    "react-hook-form": "^7.49.2",
    "react-intersection-observer": "^9.13.1",
    "react-portable-text": "^0.6.0",
    "react-transition-group": "^4.4.5",
    "react-type-animation": "^3.2.0",
    "sanity": "^3.65.0",
    "sanity-plugin-mux-input": "^2.4.0",
    "server-only": "0.0.1",
    "smartquotes": "^2.3.2",
    "styled-components": "6.1.8",
    "yup": "^1.3.3"
  },
  "devDependencies": {
    "@next/bundle-analyzer": "^14.1.0",
    "@svgr/webpack": "^8.1.0",
    "@types/react": "18.2.48",
    "autoprefixer": "10.4.16",
    "eslint": "8.55.0",
    "eslint-config-next": "14.0.3",
    "eslint-plugin-simple-import-sort": "10.0.0",
    "postcss": "8.4.32",
    "prettier": "3.1.0",
    "prettier-plugin-packagejson": "2.4.7",
    "prettier-plugin-tailwindcss": "0.5.9",
    "sass": "^1.69.5",
    "tailwindcss": "3.3.6",
    "typescript": "5.3.3"
  }
}
AI Update

I can see you're experiencing issues with array fields in Sanity Studio. While your preview config looks fine, this type of problem is typically caused by duplicate installations of the sanity package in your dependency tree rather than issues with your code.

Looking at your package.json, I notice you have "react": "^18.3.0" and "react-dom": "18.2.0". While these are on different minor versions, this shouldn't be the root cause - the caret (^) in "^18.3.0" means npm will accept any 18.x version, so both will resolve to compatible React 18 versions. Sanity requires React and React DOM to be on the same major version, which yours are.

The real culprit is usually multiple sanity package versions. This commonly happens when:

  • A plugin depends on a different version of sanity than your main dependency
  • You have both sanity and @sanity/base installed (legacy issue)
  • Your lock file has gotten out of sync

Here's what to try:

  1. Check for duplicate sanity packages:
npm ls sanity

If you see multiple versions listed, that's your problem.

  1. Clean install everything:
rm -rf node_modules package-lock.json
npm install
  1. If that doesn't work, check your plugins. I see you're using sanity-plugin-mux-input@2.4.0 - make sure it's compatible with sanity@3.65.0. You might need to update it:
npm update sanity-plugin-mux-input
  1. Update Sanity itself - you're on 3.65.0, but there have been many bug fixes since then:
npm install sanity@latest

About those React versions: While not the main issue, you could standardize them to avoid any potential edge cases:

"react": "^18.2.0",
"react-dom": "^18.2.0"

One more thing: I notice you're using styled-components@6.1.8, but Sanity Studio v3 uses styled-components v5 internally. This shouldn't cause the array field issue specifically, but could cause other styling conflicts if you're building custom Studio components.

Try the clean install first - that resolves most "unusable field" issues. If it persists, check the browser console for specific error messages that might point to which package is causing the conflict.

hello! Can you share the schema for the document type in your screen recordings? Does it use any custom components?
Hey
user N
🙂 It’s not anything out of the ordinary (I don’t think!), and the weird thing is – was working completely fine until I revisited the project this week. A previous commit from May was working perfectly, and continues to work in hosted form, but if I open that commit now, the same issue occurs locally:

import { ImagesIcon, ImageIcon, PlayIcon } from '@sanity/icons'
import { EpisodeIcon } from '@/sanity/lib/icons'
import { defineArrayMember, defineField, defineType } from 'sanity'

export default defineType({
  name: 'episode',
  title: 'Episode',
  type: 'document',
  icon: EpisodeIcon,
  // Uncomment below to have edits publish automatically as you type
  // liveEdit: true,
  fields: [
    defineField({
      name: 'title',
      description: 'This field is the title of your episode.',
      title: 'Title',
      type: 'string',
      validation: (rule) => rule.required(),
    }),
    defineField({
      name: 'number',
      description: 'This field is the number of your episode.',
      title: 'Number',
      type: 'number',
    }),
    defineField({
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
        isUnique: (value, context) => context.defaultIsUnique(value, context),
      },
      validation: (rule) => rule.required(),
    }),
    defineField({
      name: 'coverImage',
      title: 'Cover Image',
      description:
        'This image will be used as the cover image for the episode. If you choose to add it to the show case episodes, this is the image displayed in the list within the homepage.',
      type: 'image',
      validation: (rule) => rule.required(),
    }),
    defineField({
      name: 'pressRelease',
      title: 'Press Release',
      type: 'file',
      options: {
        storeOriginalFilename: true,
      },
    }),
    defineField({
      name: 'cv',
      title: 'Artist's CV',
      type: 'file',
      options: {
        storeOriginalFilename: true,
      },
    }),
    defineField({
      name: 'portfolio',
      title: 'Artist's Portfolio',
      type: 'file',
      options: {
        storeOriginalFilename: true,
      },
    }),
    // defineField({
    //   name: 'readMore',
    //   title: 'Read More',
    //   type: 'reference',
    //   to: [{ type: 'writing' }],
    // }),
    defineField({
      name: 'duration',
      title: 'Duration',
      type: 'duration',
    }),
    defineField({
      name: 'location',
      title: 'Location',
      type: 'string',
      validation: (rule) => rule.required(),
    }),
    // Names (array) of people involved (string)
    defineField({
      name: 'names',
      title: 'Names',
      type: 'array',
      of: [{ type: 'string' }],
    }),
    // Images (array) of artwork images (image) with caption (block content), credit (block content) and alt text (string)
    defineField({
      name: 'images',
      title: 'Media',
      type: 'array',
      // require at least one image
      validation: (rule) => rule.required().min(1),
      of: [
        defineField({
          type: 'image',
          icon: ImageIcon,
          name: 'image',
          title: 'Image',
          options: {
            hotspot: true,
          },
          initialValue: {
            layout: 'default',
          },
          preview: {
            select: {
              media: 'asset',
              title: 'caption',
            },
          },
          fields: [
            // layout option
            defineField({
              name: 'layout',
              title: 'Layout',
              type: 'string',
              options: {
                list: [
                  { title: 'Default', value: 'default' },
                  { title: 'Full Bleed', value: 'fullBleed' },
                ],
              },
            }),
            defineField({
              name: 'caption',
              title: 'Caption',
              type: 'blockContentSimple',
            }),
            defineField({
              name: 'credit',
              title: 'Credit',
              type: 'blockContentSimple',
            }),
            defineField({
              name: 'alt',
              type: 'string',
              title: 'Alt text',
              description:
                'Alternative text for screenreaders. Falls back on caption if not set',
            }),
          ],
        }),
        // mux video
        defineField({
          name: 'video',
          title: 'Video',
          type: 'object',
          icon: PlayIcon,
          initialValue: {
            layout: 'default',
          },
          fields: [
            defineField({
              name: 'video',
              title: 'Video',
              type: 'mux.video',
              validation: (rule) => rule.required(),
            }),
            defineField({
              name: 'layout',
              title: 'Layout',
              type: 'string',
              description: 'If full bleed, no controls will be shown and the video will be muted + autoplay',
              options: {
                list: [
                  { title: 'Default', value: 'default' },
                  { title: 'Full Bleed', value: 'fullBleed' },
                ],
              },
              hidden: () => true
            }),
            defineField({
              name: 'caption',
              title: 'Caption',
              type: 'blockContentSimple',
            }),
            defineField({
              name: 'credit',
              title: 'Credit',
              type: 'blockContentSimple',
            }),
          ],
          preview: {
            select: {
              caption: 'caption',
              videoStill: 'video.asset.data.playback_ids.0.id',
            },
            prepare: ({ caption, videoStill }) => {
              let title = caption || 'Video';
              let asset = null
              if (videoStill) {
                asset = <img src={ '<https://image.mux.com/>' + videoStill + '/thumbnail.jpg' } />
              }
              return {
                title,
                media: asset
              }
            }
          }
        }),
      ],
    }),

    defineField({
      name: 'body',
      title: 'Exhibition Text',
      type: 'blockContent',
      validation: (rule) => rule.max(155).required(),
    }),

    // defineField({
    //   name: 'overview',
    //   description:
    //     'Used both for the <meta> description tag for SEO, and episode subheader.',
    //   title: 'Overview',
    //   type: 'blockContentSimple',
    //   validation: (rule) => rule.max(155).required(),
    // }),


  ],
  preview: {
    select: {
      title: 'title',
      names: 'names',
      firstArtist: 'names.0',
      artistsLength: 'names.length',
      media: 'coverImage',
    },
    prepare({ title, names, firstArtist, artistsLength, media }) {

      // console.log('names', names);
      // console.log('firstArtist', firstArtist);

      let subtitle = firstArtist
      if (artistsLength > 1) {
        subtitle = `With ${firstArtist} and ${artistsLength - 1} other(s)`
      }

      return {
        title,
        subtitle,
        media
      }
    },
  }
})
Thanks! Taking a look.Did the version of Studio change between the May commit and now?
It didn’t, and then I tried updating Sanity to 3.65.0 and it sadly hasn’t helped!
Thank you!
Out of curiosity, how many items are inside Media?
Nothing looks out of place with your schema. I'm wondering if there's been a significant increase in the number of items that should be in the Media array since the May commit.
user N
annoyingly, no, there hasn’t – it’s 69 items, but if I open the studio on the old commit published on Vercel, it just works! If I checkout that commit locally, it’s ceased working, and same with new builds on Vercel.
head scratcher
Alright, give me a bit to chase down a couple things and we'll see if we can get this sorted.
One more question real quick—Do you mind to open a document in Inspect (upper right kebab menu) and see if the contents of the json look correct for the array?Mind to send a screenshot of one of the items in the json as well?
Thank you!! Yes they look good to me – here you go, everything I’d expect and crucially a _key, _type etc.
My friend also using Next Sanity has just seen my screen and is having this issue today too! So I wondered if it’s stemming from that? I’m mostly using Nuxt/Vue these days and hadn’t come across it!
Interesting, thanks for the added info! I'm going to get an extra set of eyes internally. I'll report back once we have more to share or next steps 🙂
user P
— Alrighty. A regression was introduced in 3.65.0 impacting arrays. Could you try rolling Sanity back to version
3.64.3
and see if the issue persists?
Updating to 3.65.0 gave me this error also. Did not help rolling back to 3.64.3 for me.
Hi
user N
– This has worked, thank you!
user A
– are you sure you’ve rolled back the version installed correctly?
user P
I will try again, if it worked for you, chances are I have incorrectly rolled back. I was sure I even deleted node_modules and the lock file before reinstalling, but will double check.
As an alternative to rolling back, this was now fixed in
v3.65.1
.
Ok, I have edited my
package.json
file and updated Sanity to 3.65.1 (
"sanity": "^3.65.1"
). Then I deleted package-lock.json and node_modules, ran
npm install
and
npm run dev
. Still I have the issue. What am I doing wrong?
If you try in a different browser, do you get the same behaviour?
No, my mistake. It works great now 🙂
Glad to hear it!
is there anyway to export all assets but with their original file names not the hashed file name? https://www.sanity.io/answers/how-to-download-all-images-from-sanity running the command from there -
sanity dataset export <dataset-name> . --types sanity.imageAsset
has all renamed assets. we know originalFilename is saved with every asset.

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?