{"record":{"id":"3c514e9860443380","repo":"litedb-org/LiteDB","slug":"mapping-error","errorCode":"MAPPING_ERROR","errorMessage":"Error in '{type.Name}' mapping: {ex.Message}","messagePattern":"Error in '(.+?)' mapping: (.+?)","errorType":"exception","errorClass":"LiteException","httpStatus":null,"severity":"error","filePath":"LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs","lineNumber":42,"sourceCode":"            return mapper;\n        }\n\n        using var cts = new CancellationTokenSource();\n        try\n        {\n            // We need to add the empty shell, because ``BuildEntityMapper`` may use this method recursively\n            var newMapper = new EntityMapper(type, cts.Token);\n            mapper = _entities.GetOrAdd(type, newMapper);\n            if (ReferenceEquals(mapper, newMapper))\n            {\n                try\n                {\n                    this.BuildEntityMapper(mapper);\n                }\n                catch (Exception ex)\n                {\n                    _entities.TryRemove(type, out _);\n                    throw new LiteException(LiteException.MAPPING_ERROR, $\"Error in '{type.Name}' mapping: {ex.Message}\", ex);\n                }\n            }\n        }\n        finally\n        {\n            // Allow the Mapper to be used for de-/serialization\n            cts.Cancel();\n        }\n\n        return mapper;\n    }\n\n    /// <summary>\n    /// Use this method to override how your class can be, by default, mapped from entity to Bson document.\n    /// Returns an EntityMapper from each requested Type\n    /// </summary>\n    protected void BuildEntityMapper(EntityMapper mapper)\n    {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/litedb-org/LiteDB/blob/f906a5f850678719e39a39a006cb66dcae563cfa/LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs#L24-L60","documentation":"Thrown by BsonMapper.GetEntityMapper as LiteException(MAPPING_ERROR) wrapping any exception raised while BuildEntityMapper reflects over a type. The offending type's name and the inner exception message are embedded. The failed mapping entry is removed from the cache so a subsequent call can retry after the type is fixed.","triggerScenarios":"Calling any operation that triggers first-time mapping of a type (Insert, Query, ToDocument) where the type has an unreflectable member, a custom ResolveMember callback that throws, an invalid attribute combination, or a member whose type cannot itself be mapped recursively.","commonSituations":"A POCO with a property whose getter throws, a struct/value type with no settable fields when IncludeFields is off, a recursive DbRef cycle, or a ResolveMember hook that throws on an unexpected member.","solutions":["Inspect the LiteException inner exception (ex.InnerException) and its message for the root cause.","Fix the offending member: make it readable/settable, add a parameterless constructor, or simplify attributes.","Temporarily simplify the type to a minimal class and re-add members until the culprit is isolated."],"exampleFix":"// before\npublic class MyEntity\n{\n    public readonly int Id; // no setter, no Id detection => mapping issues\n}\n\n// after\npublic class MyEntity\n{\n    public int Id { get; set; }\n}","handlingStrategy":"try-catch","validationCode":"// Validate the type is mappable at startup against a known-good contract:\n// - has a parameterless constructor or a [BsonCtor] constructor\n// - has an Id-named property, a [BsonId] member, or an Id mapped via EntityBuilder\n// - all serialized members are readable","typeGuard":null,"tryCatchPattern":"try { mapper.GetEntityMapper(typeof(T)); }\ncatch (LiteException ex) when (ex.Code == LiteException.MAPPING_ERROR)\n{\n    // ex.InnerException holds the root-cause exception and message\n    throw new InvalidOperationException($\"Type {typeof(T)} cannot be mapped: {ex.InnerException?.Message}\", ex);\n}","preventionTips":["Warm up entity mapping at startup to fail fast with a clear error.","Keep POCOs simple: parameterless ctor, settable Id property.","Inspect ex.InnerException for the true cause rather than the wrapper message."],"tags":["mapper","mapping","reflection","entity"],"backgroundTag":null,"analyzedSha":"f906a5f850678719e39a39a006cb66dcae563cfa","analyzedAt":"2026-08-13T21:56:30.148Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}