Manually setting `_createdAt` field after creation time in Sanity.io.

3 replies
Last updated: Oct 17, 2023
Is there some way to manually set
doc._createdAt
after creation time? I ran a migration to import a bunch of Markdown docs last week, but sadly forgot to apply the original dates to this field.
AI Update

Unfortunately, _createdAt cannot be modified after a document is first created, even through migrations. According to Sanity's documentation on setting created and modified dates:

You can set the _createdAt attribute the first time you create a document, but it cannot be modified in subsequent mutations (without deleting and recreating the document).

Your options for fixing this:

The best approach is to create your own datetime fields in your schema for editorial purposes. These fields are fully editable and can be set during migration or updated anytime:

defineField({
  name: 'originalCreatedAt',
  type: 'datetime',
  title: 'Original Creation Date',
  description: 'The original creation date from the imported content',
})

You can then populate these fields with a migration script using the migration tooling or the Sanity Client.

2. Delete and recreate documents (Nuclear option)

If you absolutely need the system _createdAt field to reflect the original dates, you'd have to:

  1. Delete the existing documents
  2. Recreate them with _createdAt set to the original dates in your create mutation

Important: When you first create a document, you CAN set _createdAt to any value you want. It's only locked after that initial creation.

3. Run a new migration with correct dates

If you still have access to your original data source, you could:

  1. Create a new dataset (or use the same one after backing up)
  2. Re-run your migration, this time including the original dates in your create mutations:
const doc = {
  _id: 'imported-post-123',
  _type: 'post',
  _createdAt: originalPost.created, // Set it during initial creation
  title: originalPost.title,
  // ... other fields
}

await client.create(doc)

The editorial date field approach (option 1) is generally the best practice, as it gives you full control over dates that matter to your content team, while the system _createdAt/_updatedAt fields track actual mutation history in Sanity.

I already have a custom
publishedAt
field that I can use for the patch
As far as I can tell though, _createdAt is read-only
Update: After some more searching it does seem like the
_
prefaced fields are readonly.
For future searchers who made the same mistake, here's what I'm doing to move forward:
• Made my custom
publishedAt
field
hidden
in my schema definition, so it will be undefined on all posts created in the future.• On my client, replaced
doc.publishedAt
with
doc.publishedAt ?? doc._createdAt
to account for old posts and future ones.

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?