-
Notifications
You must be signed in to change notification settings - Fork 156
Description
Hello, migrations will go in a corrupted state when there is a validation error during the transform entries phase.
I have a migration that looks like this:
module.exports.description = 'Update content model display names';
module.exports.up = (migration) => {
const richLink = migration.editContentType('richLink')
richLink.createField('internalName')
.name('Name(internal)')
.type('Symbol')
.localized(false)
.required(true)
richLink.displayField('internalName')
// ...
migration.transformEntries({
contentType: 'richLink',
from: ['name'],
to: ['internalName'],
shouldPublish: 'preserve',
transformEntryForLocale: async (fromFields, currentLocale, { id }) => {
console.log(`transformEntry #${id} For Locale ${currentLocale}, with fields: ${JSON.stringify(fromFields)}`)
return {
internalName: (fromFields.name && fromFields.name[currentLocale]) || `untitled richlink ${id}`
};
},
});
}
module.exports.down = (migration) => {
const richLink = migration.editContentType('richLink')
.displayField('name')
richLink.deleteField('internalName')
}
When I run this migration, I have a case where some invalid entries (with fields not passing validation, easy to create with drafts) are causing the migration to fail:
Processing richLink
up : 20250623195905-rich-link-content-name.js
transformEntry #4Q7REDACTED For Locale fr-FR, with fields: {"name":{"fr-FR":"Plus d'info"}}
transformEntry #4Q7REDACTED For Locale pl-PL, with fields: {"name":{"fr-FR":"Plus d'info"}}
transformEntry #5NmREDACTED For Locale fr-FR, with fields: {}
transformEntry #5NmREDACTED For Locale pl-PL, with fields: {}
# ... (REDACTED for concision)
The following migration has been planned
Environment: dev
Update Content Type richLink
- displayField: "internalName"
Create field internalName
- name: "Name(internal)"
- type: "Symbol"
- localized: false
- required: true
Publish Content Type richLink
Update field controls for Content Type richLink
Update field internalName
- widgetId: "singleLine"
- widgetNamespace: "builtin"
- helpText: "...REDACTED for concision"
Transform entries for richLink
- from: name
- to: internalName
[08:23:02] Update Content Type richLink [started]
[08:23:02] Making requests [started]
[08:23:02] Making requests (1/2) [title changed]
[08:23:02] → PUT /content_types/richLink at V15
[08:23:02] Making requests (2/2) [title changed]
[08:23:02] → PUT /content_types/richLink/published at V16
[08:23:03] Making requests (2/2) [completed]
[08:23:03] Update Content Type richLink [completed]
[08:23:03] Update field controls for Content Type richLink [started]
[08:23:03] Making requests [started]
[08:23:03] Making requests (1/1) [title changed]
[08:23:03] → PUT /content_types/richLink/editor_interface at V10
[08:23:03] Making requests (1/1) [completed]
[08:23:03] Update field controls for Content Type richLink [completed]
[08:23:03] Transform entries for richLink [started]
[08:23:03] Making requests [started]
[08:23:03] Making requests (1/27) [title changed]
[08:23:03] → PUT /entries/5sc8Y18Ae6A7Pb7gp3zpyi at V11
[08:23:03] Making requests (2/27) [title changed]
[08:23:03] → PUT /entries/5sc8Y18Ae6A7Pb7gp3zpyi/published at V12
# ... (REDACTED for concision)
[08:23:11] Making requests (27/27) [failed]
[08:23:11] → Batch failed
[08:23:11] Transform entries for richLink [failed]
[08:23:11] → Batch failed
🚨 Migration unsuccessful:
Batch failed
Error: {"status":"Unprocessable Entity","message":"Validation error","details":{"errors":[{"name":"type","type":"Symbol","value":"/category/REDACTED","details":"Maximum Symbol length is 255 characters","path":["fields","link","fr-FR"]}]},"url":"https://api.contentful.com/spaces/REDACTED/environments/dev/entries/REDACTED"}
Please check the errors log for more details: /builds/invivodf/contentful/migration-contentful/errors-1751530982718.log
error : Error: Batch failed
BatchError: Batch failed
at Task.task (/builds/invivodf/contentful/migration-contentful/node_modules/contentful-migrate/lib/run.js:116:21)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
batch: {
intent: EntryTransformIntent {
type: 'contentType/transformEntries',
meta: [Object],
payload: [Object]
},
requests: [
[Object], [Object], [Object],
[Object], [Object], [Object],
[Object], [Object], [Object],
[Object], [Object], [Object],
[Object], [Object], [Object],
[Object], [Object], [Object],
[Object], [Object], [Object],
[Object], [Object], [Object],
[Object], [Object], [Object]
],
validationErrors: [],
runtimeErrors: []
},
errors: [
Error: {"status":"Unprocessable Entity","message":"Validation error","details":{"errors":[{"name":"type","type":"Symbol","value":"/category/REDACTED","details":"Maximum Symbol length is 255 characters","path":["fields","link","fr-FR"]}]},"url":"https://api.contentful.com/spaces/REDACTED/environments/dev/entries/REDACTED"}
at /builds/invivodf/contentful/migration-contentful/node_modules/contentful-migrate/lib/run.js:111:36
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Task.task (/builds/invivodf/contentful/migration-contentful/node_modules/contentful-migrate/lib/run.js:102:15)
],
context: [Object: null prototype] {}
The problem is, the schema alterations are not rollbacked, and yet the migration content is still at its previous. This cause subsequent migration run to enter a corrupt state, when it tries to run the contentModel migration again even though it has not been rollbacked.
I expect to the migration to be rollbacked, or there should be at least a flag that marks the last migration as failed and stop the contentful-migration from running it again.
Also, I expect drafts to not be validated, when shouldPublish is set to 'preserve'
or false
.