Custom NSMigrationPolicy methods not invoked when NSMappingModel is created in code

Hi, I’m running into an issue with Core Data migrations using a custom NSMappingModel created entirely in Swift (not using .xcmappingmodel files).

Setup: • I’m performing a migration with a manually constructed NSMappingModel • One of the NSEntityMapping instances is configured as follows: • mappingType = .customEntityMappingType (or .transformEntityMappingType) • entityMigrationPolicyClassName is set to a valid subclass of NSEntityMigrationPolicy • The class implements the expected methods like: @objc func createDestinationInstances(…) throws { … } @objc func createCustomDestinationInstance(…) throws -> NSManagedObject { … }

The policy class is instantiated (confirmed via logging in init()), but none of the migration methods are ever called.

I have also tried adding valid NSPropertyMapping instances with real valueExpression bindings to force activation, but that didn’t make a difference.

Constraints: • I cannot use .xcmappingmodel files in this context due to transformable attributes not compatible with the visual editor. • Therefore, I need the entire mapping model to be defined in Swift.

Workaround:

As a temporary workaround, I’m migrating the data manually using two persistent stores and NSManagedObjectContext, but I’d prefer to rely on NSMigrationManager as designed.

Question:

Is there a known limitation that prevents Core Data from invoking NSMigrationPolicy methods when using in-memory NSMappingModel instances? Or is there any specific setup required to trigger them when not loading from .xcmappingmodel?

Thanks in advance.

Answered by DTS Engineer in 859061022

Using custom mapping models isn't recommended. To handle changes that lightweight migration doesn't support, consider using staged migration, as mentioned in this post.

Now to your question:

Is there a known limitation that prevents Core Data from invoking NSMigrationPolicy methods when using in-memory NSMappingModel instances? Or is there any specific setup required to trigger them when not loading from .xcmappingmodel?

I haven't ever looked deeply into an in-memory NSMappingModel instance, but to debug the issue, you can probably create an .xcmappingmodel file that works, load it into memory using NSMappingModel.init(contentsOf:), and then compare it with what you created. You might be able to figure out the difference from there.

I'm unaware of any known limitation.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Using custom mapping models isn't recommended. To handle changes that lightweight migration doesn't support, consider using staged migration, as mentioned in this post.

Now to your question:

Is there a known limitation that prevents Core Data from invoking NSMigrationPolicy methods when using in-memory NSMappingModel instances? Or is there any specific setup required to trigger them when not loading from .xcmappingmodel?

I haven't ever looked deeply into an in-memory NSMappingModel instance, but to debug the issue, you can probably create an .xcmappingmodel file that works, load it into memory using NSMappingModel.init(contentsOf:), and then compare it with what you created. You might be able to figure out the difference from there.

I'm unaware of any known limitation.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Hi, Following the advice I received here, I switched to using NSStagedMigrationManager instead of trying to drive a custom NSMappingModel entirely in code.

I now have a staged migration pipeline with two stages: • Stage 1 (V1 → V2): a lightweight migration. • Stage 2 (V2 → V3): a custom migration where I re-archive a Transformable attribute (object) from a legacy ValueTransformer to a safe binary format (GraphArchiver).

Both models are built entirely at runtime (no .xcdatamodeld files). Each model has a unique versionChecksum string (hardcoded identifiers: "GraphCK_MigrationV1", "GraphCK_MigrationV2", "GraphCK_MigrationV3").

When I run the staged migration manager with these two stages, I consistently hit this exception:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Duplicate version checksums across stages detected.'

Debug logging shows:

Stage1 checksums: ["GraphCK_MigrationV1", "GraphCK_MigrationV2"] Stage2 checksums: ["GraphCK_MigrationV2", "GraphCK_MigrationV3"]

So the identifiers look correct and distinct, but the framework still complains about “duplicate checksums across stages”.

Question: Is this error expected when building models entirely at runtime? Do we need to persist .mom files or .xcmappingmodel files so the checksums are stable? Or is there a supported way to run a staged migration pipeline from runtime-constructed models only?

Any insight on how to avoid the “duplicate version checksums” error when using NSStagedMigrationManager with runtime models would be greatly appreciated.

I don't think building models at runtime has anything wrong, but that is not quite a common use case because folks typically use model files.

Do you have a minimal project that demonstrates the issue? If you can share, I'd find time to take a closer look.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Custom NSMigrationPolicy methods not invoked when NSMappingModel is created in code
 
 
Q