{"record":{"id":"da79aa0404e3a505","repo":"dotnet/efcore","slug":"the-type-of-the-idproperty-property-on-entit","errorCode":null,"errorMessage":"The type of the '{idProperty}' property on '{entityType}' is '{propertyType}'. All 'id' properties must be strings or have a string value converter.","messagePattern":"The type of the '(.+?)' property on '(.+?)' is '(.+?)'\\. All 'id' properties must be strings or have a string value converter\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs","lineNumber":444,"sourceCode":"        var primaryKey = entityType.FindPrimaryKey();\n        if (primaryKey == null\n            || !entityType.IsDocumentRoot())\n        {\n            return;\n        }\n\n        var idProperty = entityType.GetProperties()\n            .FirstOrDefault(p => p.GetJsonPropertyName() == CosmosJsonIdConvention.IdPropertyJsonName);\n        if (idProperty == null)\n        {\n            throw new InvalidOperationException(CosmosStrings.NoIdProperty(entityType.DisplayName()));\n        }\n\n        var idType = idProperty.GetTypeMapping().Converter?.ProviderClrType\n            ?? idProperty.ClrType;\n        if (idType != typeof(string))\n        {\n            throw new InvalidOperationException(\n                CosmosStrings.IdNonStringStoreType(idProperty.Name, entityType.DisplayName(), idType.ShortDisplayName()));\n        }\n\n        var partitionKeyPropertyNames = entityType.GetPartitionKeyPropertyNames();\n        if (partitionKeyPropertyNames.Count == 0)\n        {\n            logger.NoPartitionKeyDefined(entityType);\n        }\n        else\n        {\n            if (entityType.BaseType != null\n                && entityType.FindAnnotation(CosmosAnnotationNames.PartitionKeyNames)?.Value != null)\n            {\n                throw new InvalidOperationException(\n                    CosmosStrings.PartitionKeyNotOnRoot(entityType.DisplayName(), entityType.BaseType.DisplayName()));\n            }\n\n            foreach (var partitionKeyPropertyName in partitionKeyPropertyNames)","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs#L426-L462","documentation":"Thrown by ValidateKeys when the property mapped to JSON \"id\" has a store type (ClrType after applying any value converter) that is not System.String. Cosmos requires the document \"id\" to be a string, so the id-mapped property must either be a string or have a value converter whose ProviderClrType is string.","triggerScenarios":"Mapping a Guid/int/long primary key to JSON \"id\" (ToJsonProperty(\"id\")) without a string value converter, defeating the convention's default behavior.","commonSituations":"Forcing a non-string PK onto \"id\"; adding ToJsonProperty(\"id\") to a numeric property; a value converter that converts to a non-string provider type.","solutions":["Keep the id-mapped property as a string (let the convention map a string PK to \"id\").","Add a value converter to string, e.g. .HasConversion(v => v.ToString(), v => Guid.Parse(v)) on the id property.","Do not remap a non-string PK onto \"id\"; let the convention synthesize the string id."],"exampleFix":"// before\nmodelBuilder.Entity<Thing>()\n    .Property(t => t.Id) // Guid\n    .ToJsonProperty(\"id\");\n\n// after\nmodelBuilder.Entity<Thing>()\n    .Property(t => t.Id)\n    .ToJsonProperty(\"id\")\n    .HasConversion(v => v.ToString(), v => Guid.Parse(v));","handlingStrategy":"validation","validationCode":"using var ctx = new MyContext();\nforeach (var e in ctx.Model.GetEntityTypes().Where(t => t.FindPrimaryKey() != null && t.IsDocumentRoot()))\n{\n    var idProp = e.GetProperties().FirstOrDefault(p => p.GetJsonPropertyName() == \"id\");\n    if (idProp is not null)\n    {\n        var storeType = idProp.GetTypeMapping().Converter?.ProviderClrType ?? idProp.ClrType;\n        Debug.Assert(storeType == typeof(string), $\"{e.Name}.{idProp.Name} id store type {storeType} is not string\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try { ctx.Model.GetModel(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"All 'id' properties must be strings\"))\n{\n    logger.LogError(ex, \"The id-mapped property is not a string and has no string converter\");\n    throw;\n}","preventionTips":["Use a string primary key for the id-mapped property, or add a string value converter.","Do not remap non-string PKs onto JSON 'id'.","Add a test asserting the id store type is string."],"tags":["cosmos","configuration","model-validation","id","value-converter"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}