{"record":{"id":"e18d475462843eaf","repo":"dotnet/efcore","slug":"the-time-to-live-for-analytical-store-was-configur","errorCode":null,"errorMessage":"The time to live for analytical store was configured to '{ttl1}' on '{entityType1}', but on '{entityType2}' it was configured to '{ttl2}'. All entity types mapped to the same container '{container}' must be configured with the same time to live for analytical store.","messagePattern":"The time to live for analytical store was configured to '(.+?)' on '(.+?)', but on '(.+?)' it was configured to '(.+?)'\\. All entity types mapped to the same container '(.+?)' must be configured with the same time to live for analytical store\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs","lineNumber":246,"sourceCode":"                {\n                    throw new InvalidOperationException(\n                        CosmosStrings.IsDiscriminatorMappingCompleteMismatch(\n                            isDiscriminatorMappingComplete, firstEntityType.DisplayName(), entityType.DisplayName(),\n                            currentIsDiscriminatorMappingComplete, container));\n                }\n            }\n\n            var currentAnalyticalTtl = entityType.GetAnalyticalStoreTimeToLive();\n            if (currentAnalyticalTtl != null)\n            {\n                if (analyticalTtl == null)\n                {\n                    analyticalTtl = currentAnalyticalTtl;\n                }\n                else if (analyticalTtl != currentAnalyticalTtl)\n                {\n                    var conflictingEntityType = mappedTypes.First(et => et.GetAnalyticalStoreTimeToLive() != null);\n                    throw new InvalidOperationException(\n                        CosmosStrings.AnalyticalTTLMismatch(\n                            analyticalTtl,\n                            conflictingEntityType.DisplayName(),\n                            entityType.DisplayName(),\n                            currentAnalyticalTtl,\n                            container));\n                }\n            }\n\n            var currentDefaultTtl = entityType.GetDefaultTimeToLive();\n            if (currentDefaultTtl != null)\n            {\n                if (defaultTtl == null)\n                {\n                    defaultTtl = currentDefaultTtl;\n                }\n                else if (defaultTtl != currentDefaultTtl)\n                {","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs#L228-L264","documentation":"Thrown by CosmosModelValidator.ValidateSharedContainerCompatibility when two document-root entity types mapped to the same Cosmos container declare different analytical-store time-to-live values via HasAnalyticalStoreTimeToLive(). Azure Cosmos DB applies analytical-store TTL at the container scope, so EF requires every type sharing a container to agree. The comparison uses entityType.GetAnalyticalStoreTimeToLive() (which already resolves to the root type's value for derived types).","triggerScenarios":"Calling modelBuilder.Entity<A>().HasAnalyticalStoreTimeToLive(60) and modelBuilder.Entity<B>().HasAnalyticalStoreTimeToLive(120) where both A and B are mapped (via ToContainer or default) to the same container, during model validation (first DbContext use).","commonSituations":"Multi-entity shared-container designs where TTL was added to one entity during a feature spike but not propagated; merging configs from two teams each owning different entities in the same container; changing the TTL value in one place after copy-pasting config.","solutions":["Pick one TTL value and apply the same HasAnalyticalStoreTimeToLive(N) to every root entity type mapped to that container.","Alternatively set TTL on a single root entity and remove the conflicting call from the other.","Centralize container-level settings in a shared OnModelCreating helper/convention so they cannot drift."],"exampleFix":"// before\nmodelBuilder.Entity<Order>().ToContainer(\"store\").HasAnalyticalStoreTimeToLive(60);\nmodelBuilder.Entity<Customer>().ToContainer(\"store\").HasAnalyticalStoreTimeToLive(120);\n\n// after\nmodelBuilder.Entity<Order>().ToContainer(\"store\").HasAnalyticalStoreTimeToLive(60);\nmodelBuilder.Entity<Customer>().ToContainer(\"store\").HasAnalyticalStoreTimeToLive(60);","handlingStrategy":"validation","validationCode":"// In a unit test or Program.cs startup, force model validation early:\nusing (var ctx = new MyContext())\n{\n    ctx.Model.GetModel(); // or ctx.GetService<IModelRuntimeInitializer>().Initialize(ctx.Model);\n}\n// Then assert container settings are uniform:\nforeach (var grp in ctx.Model.GetEntityTypes()\n    .Where(e => e.FindPrimaryKey() != null && e.GetContainer() != null)\n    .GroupBy(e => e.GetContainer()))\n{\n    var ttls = grp.Select(e => e.GetAnalyticalStoreTimeToLive()).Distinct().ToList();\n    Debug.Assert(ttls.Count <= 1, $\"Container {grp.Key} has conflicting analytical TTLs\");\n}","typeGuard":null,"tryCatchPattern":"try { ctx.Database.EnsureCreated(); } // forces validation\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"time to live for analytical store\"))\n{\n    logger.LogError(ex, \"Analytical TTL mismatch across entities in a shared container\");\n    throw;\n}","preventionTips":["Centralize all container-level Cosmos settings (TTL, throughput, partition key) in a single ApplyContainerDefaults(entity, container) helper.","Write a model-validation unit test that builds the context and groups entities by container, asserting each container-level setting is uniform.","Run dotnet ef migrations add / DbContext construction in CI to surface model errors before deploy."],"tags":["cosmos","configuration","model-validation","ttl","shared-container"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}