"Fixing 'Mutation' Issue Due to Insufficient Permissions in React and NextJs Web App with Sanity CMS"

2 replies
Last updated: Jul 26, 2023
Hello, is anyone here know how to fix "Mutation" issue due to Insufficient permissions. I have my web app built with React and NextJs and Sanity for CMS. I cannot post comments on my blog (but it works in my local, except in vercel) and the error is what is shown below everytime i post comments. Thank you.

ClientError: Mutation(s) failed with 1 error(s)
at onResponse (/var/task/node_modules/@sanity/client/lib/http/request.js
:19:13) at applyMiddleware (/var/task/node_modules/get-it/lib-node/util/middlewareReducer.js
:15:15) at onResponse (/var/task/node_modules/get-it/lib-node/index.js
:89:22) at /var/task/node_modules/get-it/lib-node/index.js
:59:55 at callback (/var/task/node_modules/get-it/lib-node/request/node-request.js
:65:46) at /var/task/node_modules/get-it/lib-node/request/node-request.js
:154:14 at DestroyableTransform.<anonymous> (/var/task/node_modules/simple-concat/index.js
:8:13) at Object.onceWrapper (node
:events:627:28) at DestroyableTransform.emit (node
:events:525:35) at endReadableNT (/var/task/node_modules/readable-stream/lib/_stream_readable.js
:1010:12) { response: {
body: { error: [Object] },
url: '
https://r4ni59be.api.sanity.io/v2023-01-30/data/mutate/production?returnIds=true&returnDocuments=true&visibility=sync ', method: 'POST',
headers: {
'content-type': 'application/json; charset=utf-8',
'x-ratelimit-limit-second': '50',
'ratelimit-limit': '50',
'ratelimit-remaining': '49',
'ratelimit-reset': '1',
'x-ratelimit-remaining-second': '49',
date: 'Tue, 25 Jul 2023 08
:42:03 GMT', 'content-encoding': 'gzip',
'server-timing': 'api;dur=14',
vary: 'Accept-Encoding, origin',
'x-sanity-shard': 'gcp-eu-w1-01-prod-1032',
'x-served-by': 'gradient-web-85dcf77667-c9hs9',
'strict-transport-security': 'max-age=15724800; includeSubDomains',
xkey: 'project-r4ni59be, project-r4ni59be-production',
via: '1.1 google',
'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000',
connection: 'close',
'transfer-encoding': 'chunked'
},
statusCode: 403,
statusMessage: 'Forbidden'
},
statusCode: 403,
responseBody: '{\n' +
' "error": {\n' +
' "description": "Mutation(s) failed with 1 error(s)",\n' +
' "items": [\n' +
' {\n' +
' "error": {\n' +
' "description": "Insufficient permissions; permission \\"create\\" required",\n' +
' "permission": "create",\n' +
' "type": "insufficientPermissionsError"\n' +
' },\n' +
' "index": 0\n' +
' }\n' +
' ],\n' +
' "type": "mutationError"\n' +
' }\n' +
'}',
details: {
description: 'Mutation(s) failed with 1 error(s)',
items: [ [Object] ],
type: 'mutationError'
}
}
AI Update

This is a classic authentication issue! The error "Insufficient permissions; permission 'create' required" with a 403 status means your Sanity client in production doesn't have write access to your dataset.

Why it works locally but not on Vercel:

Locally, you're likely authenticated through sanity login, which gives your client write permissions. But in production on Vercel, your client has no authentication token, so it can't create documents.

The Solution:

You need to create an API token with write permissions and add it to your Vercel environment:

1. Create a write token in Sanity:

  • Go to manage.sanity.io (or run npx sanity@latest manage)
  • Select your project
  • Navigate to APITokens
  • Click Add API token
  • Give it a name like "Production Write Token"
  • Set permissions to Editor or Contributor (avoid Admin unless necessary)
  • Copy the token immediately (you won't see it again!)

2. Add the token to Vercel:

  • Go to your Vercel project settings
  • Navigate to Environment Variables
  • Add: SANITY_API_TOKEN with your token value
  • Make sure it's enabled for Production
  • Redeploy your application

3. Update your Sanity client:

import { createClient } from '@sanity/client'

export const client = createClient({
  projectId: 'your-project-id',
  dataset: 'production',
  apiVersion: '2023-01-30',
  useCdn: false, // Important for mutations!
  token: process.env.SANITY_API_TOKEN, // Add this
})

⚠️ CRITICAL SECURITY WARNING:

Never expose write tokens in client-side code! If you're creating comments from the browser, you MUST use a Next.js API route to keep the token server-side.

Proper implementation with API route:

Create /pages/api/comments.js (or /app/api/comments/route.js for App Router):

import { createClient } from '@sanity/client'

const client = createClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
  apiVersion: '2023-01-30',
  useCdn: false,
  token: process.env.SANITY_API_TOKEN, // Server-side only!
})

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ message: 'Method not allowed' })
  }

  try {
    const result = await client.create({
      _type: 'comment',
      ...req.body, // Your comment data
    })
    res.status(200).json(result)
  } catch (error) {
    res.status(500).json({ error: error.message })
  }
}

Then call this API route from your frontend instead of using the Sanity client directly.

This keeps your write token secure on the server while allowing your comment functionality to work in production. For more details on token security, check out the Sanity documentation on API tokens.

You’ll need to include a token in order to write to your dataset from outside of the Studio.
Yeah thank you. I already solved this issue. I just forgot to include the env variables of token

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?