Migration script not fetching i18n documents with dot notation IDs
domain: 'website'
I have used:
https://www.sanity.io/docs/migrating-data
Which works, for document types, images and assets. Hooray! Now, the pickle I'm in, is that I need to migrate
i18n documents as well. HOWEVER, even if:
• I am successfully authenticated
• My role is
administrator• And my token is
EDITORIt looks like the, Sanity does not fetch this documents. My query, since I want to pull all documents, is just
*[]
Below I attach a snipped of my migration script. It would be really helpful if anybody had some insight. My current hypothesis is that I can not pull this kind of id:
i18n.<sanity-id>.en_DEfor example because of the restrictions explained here: https://www.sanity.io/docs/ids#fdc25ada5db2
Thank you all in advance
❤️
I can help you with this! The issue you're experiencing is related to how Sanity's API handles documents with specific ID patterns, particularly those used by internationalization plugins.
The Core Issue: Document ID Patterns and CDN Access
When using documents with dots in their _id (like i18n.<sanity-id>.en_DE), these are treated as "private" documents by Sanity's CDN. According to the Sanity documentation on document IDs, dots in document IDs create a subpath structure that makes documents private - they won't be exposed through the CDN by default, even with proper authentication.
The Solution: Bypass the CDN
When creating your Sanity client for the migration script, you must set useCdn: false:
import {createClient} from '@sanity/client'
const client = createClient({
projectId: 'your-project-id',
dataset: 'your-dataset',
token: process.env.SANITY_TOKEN,
useCdn: false, // Critical for accessing documents with dots in IDs
apiVersion: '2024-01-01'
})Setting useCdn: false ensures your queries go directly to Sanity's origin API rather than through the CDN layer. The origin API properly respects your authentication token and will return documents with subpath IDs (like your i18n documents).
Complete Migration Example
Here's how your migration script should look:
import {createClient} from '@sanity/client'
import {defineMigration, at, set} from '@sanity/migrate'
const client = createClient({
projectId: 'your-project-id',
dataset: 'your-dataset',
token: process.env.SANITY_TOKEN,
useCdn: false, // Essential!
apiVersion: '2024-01-01'
})
export default defineMigration({
title: 'Add domain field to all documents',
async *migrate(documents) {
// This will now fetch ALL documents, including i18n ones
for await (const doc of documents()) {
yield {
documentId: doc._id,
patches: [
at('domain', set('website'))
]
}
}
}
})Understanding Your i18n Setup
Based on your ID pattern i18n.<sanity-id>.en_DE, it looks like you might be using a custom internationalization setup or an older version of an i18n plugin. The document-internationalization plugin uses different patterns:
- Version 2+: Uses
translation.metadatadocuments - Version 1: Uses IDs like
{base-id}__i18n_{locale}
Your pattern with dots is creating private documents, which is why the CDN isn't returning them.
Additional Troubleshooting
Test your query first: In Vision plugin, verify the documents exist:
*[_id match "i18n.*"]Verify token permissions: Your
EDITORtoken should have read/write access to all document types.Check the migration client: Make sure the client you pass to the migration functions also has
useCdn: falseset.
The useCdn: false setting is the key to solving your issue - it's a common gotcha when working with documents that have special ID patterns!
Show original thread18 replies
Was this answer helpful?
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.