Upgrade @sanity/client from an older major version

Find which @sanity/client version you run, why pre-v3 clients with a token skip the API CDN, and what changed in each major version.

Each major version of @sanity/client changes some defaults or requirements. On a project that still runs an old major version, those changes decide whether your queries reach the API CDN, how failed requests are handled, and which documents your queries return.

This guide shows how to find which version you run, explains the pre-v3 behavior that sends token-authenticated queries to the live API, and lists what to update for each major version.

Prerequisites:

  • Access to the project's package.json and lockfile.
  • Node.js 22.12 or later to run v8. If you can't upgrade Node.js, upgrade to v7, which runs on Node.js 20.

Check which version of @sanity/client you run

List every installed copy of the client. Other packages can depend on their own, older copy, so check each line of the output, not only your direct dependency:

npm ls @sanity/client

To check the behavior instead of the version number, read the resolved configuration from a client instance. client.config().useCdn returns the value the client actually uses, which can differ from the value you passed in.

Tokens turn off the API CDN before v3

In @sanity/client v2 and earlier, setting a token turns useCdn off, even when you pass useCdn: true. The client sends every query to the live, uncached API at api.sanity.io, so token-authenticated traffic never benefits from the API CDN and counts against the live API's rate limits. A frontend that sends a token on every request can hit 429 Too Many Requests responses while its configuration says useCdn: true.

In Node.js, v2 and earlier log a warning when you create the client:

You have set `useCdn` to `true` while also specifying a token. This is usually not what you want. The CDN cannot be used with an authorization token, since private data cannot be cached. See https://docs.sanity.io/help/js-client-usecdn-token for more information.

In a browser on a domain other than localhost, the client logs nothing, so the switch to the live API goes unnoticed.

Starting with v3.0.0, a client with a token and useCdn: true sends queries to the API CDN at apicdn.sanity.io. The API CDN caches authenticated responses separately for each token. To fix the behavior, upgrade to v3 or later; the latest major version is the recommended target.

The same configuration on v2 and on v8:

const sanityClient = require('@sanity/client')

// On v2 and earlier, the token turns useCdn off.
// Every query goes to the live API at api.sanity.io.
const client = sanityClient({
  projectId: '',
  dataset: 'production',
  token: process.env.SANITY_API_READ_TOKEN,
  useCdn: true,
})

console.log(client.config().useCdn) // false

Choose useCdn for each token client

What changed in each major version

Read every section between your current version and the version you upgrade to. Each section links to the full release notes or migration guide in the @sanity/client repository.

v3

  • A token combined with useCdn: true uses the API CDN instead of the live API.
  • Requires Node.js 12 or later.
  • Removes the deprecated merge patch operation and the deprecated document property on the assets.upload response.
  • client.observable.fetch() returns a cold observable.

Details: v3.0.0 release notes.

v4

  • Expands ES module support. Some bundler and runtime setups might need configuration changes.

Details: v4.0.0 release notes.

v5

  • Replaces the default export with the named export createClient. Change import sanityClient from '@sanity/client' to import {createClient} from '@sanity/client'. From v5.2.1, the default export works again, but it's deprecated and logs a warning.
  • Requires Node.js 14.18 or later and no longer ships ES5 output.
  • Removes client.assets.getImageUrl() (use @sanity/image-url), client.assets.delete() (use client.delete()), and client.clientConfig (use client.config()).

Details: Migrating from v4.

v6

  • useCdn defaults to true. Set useCdn: false to keep querying the live API.
  • Retries GET and HEAD requests and queries automatically when the API responds with 429, 502, or 503. Also retries GET and HEAD requests on network errors. If your application has its own retry logic, remove it or set maxRetries: 0. See Automatic retries.

Details: Migrating from v5.

v7

  • Requires Node.js 20 or later.

Details: v7.0.0 release notes.

v8

  • Requires Node.js 22.12 or later and ships as ES modules only. require('@sanity/client') still works on Node.js 22.12 or later.
  • TypeScript projects need moduleResolution set to node16, nodenext, or bundler.
  • Removes the requester option, the per-request proxy option, and the UMD bundle.
  • Retries DNS ENOTFOUND errors for GET and HEAD requests. Set maxRetries: 0 to fail immediately.
  • Adds the HTTP status text to ClientError and ServerError messages, for example HTTP 400 Bad Request. Update any code that matches on error message text.

Details: Migrating from v7.

Set apiVersion to control the default perspective

Which documents a query returns by default depends on the apiVersion you set, not on the client's major version. Requests with an apiVersion earlier than 2025-02-19 use the raw perspective, which returns drafts alongside published documents when the request includes a token. From 2025-02-19, the default is published.

Clients older than v2.7.0 have no apiVersion option and always use API version v1. When you upgrade, set apiVersion to a fixed date and test your queries against it. See API versioning.

Fix the ERR_REQUIRE_ESM error after upgrading to v8

If require('@sanity/client') fails with Error [ERR_REQUIRE_ESM]: require() of ES Module, the project usually runs v8 on a Node.js version earlier than 22.12. When npm installs v8 on those versions, it also warns npm warn EBADENGINE Unsupported engine. Upgrade Node.js to 22.12 or later. If you can't upgrade Node.js, install v7 with npm install @sanity/client@7. v7 runs on Node.js 20 or later.

Next steps

Was this page helpful?