{"record":{"id":"eea5681069321631","repo":"litedb-org/LiteDB","slug":"method-node-method-name-not-available-to-convert","errorCode":null,"errorMessage":"Method {node.Method.Name} not available to convert to BsonExpression ({node.ToString()}).","messagePattern":"Method (.+?) not available to convert to BsonExpression \\((.+?)\\)\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"LiteDB/Client/Mapper/Linq/LinqExpressionVisitor.cs","lineNumber":228,"sourceCode":"            var hasResolver = TryGetResolver(node.Method.DeclaringType, out var type);\n\n            if (node.Method.DeclaringType == typeof(Enumerable) && node.Arguments.Count > 0)\n            {\n                var first = node.Arguments[0].Type;\n\n                if (first.IsGenericType && first.GetGenericTypeDefinition() == typeof(IGrouping<,>))\n                {\n                    type = _resolver[typeof(IGrouping<,>)];\n                    hasResolver = true;\n                }\n            }\n\n            if (!hasResolver)\n            {\n                // if method are called by parameter expression and it's not exists, throw error\n                var isParam = ParameterExpressionVisitor.Test(node);\n\n                if (isParam) throw new NotSupportedException($\"Method {node.Method.Name} not available to convert to BsonExpression ({node.ToString()}).\");\n\n                // otherwise, try compile and execute\n                var value = this.Evaluate(node);\n\n                base.Visit(Expression.Constant(value));\n\n                return node;\n            }\n\n            // otherwise I have resolver for this method\n            var pattern = type.ResolveMethod(node.Method);\n\n            if (pattern == null) throw new NotSupportedException($\"Method {Reflection.MethodName(node.Method)} in {node.Method.DeclaringType.Name} are not supported when convert to BsonExpression ({node.ToString()}).\");\n\n            // run pattern using object as # and args as @n\n            this.ResolvePattern(pattern, node.Object, node.Arguments);\n\n            return node;","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/litedb-org/LiteDB/blob/f906a5f850678719e39a39a006cb66dcae563cfa/LiteDB/Client/Mapper/Linq/LinqExpressionVisitor.cs#L210-L246","documentation":"Thrown by VisitMethodCall when the method's declaring type has NO registered resolver and the method is called on a parameter expression (isParam is true). LiteDB cannot translate a method call that operates on a document field if it does not know how to resolve the declaring type. If the method is NOT on a parameter (e.g., a closure constant), the visitor instead compiles and evaluates it in memory.","triggerScenarios":"Calling an instance method or extension method on a query parameter where the method's declaring type has no ITypeResolver. For example x => x.CustomObj.DoSomething() where CustomObj is a user type with no resolver, or x => x.Items.MyExtension() where MyExtension is a custom extension method.","commonSituations":"Using custom extension methods or instance methods on user-defined types inside LINQ queries. Assuming LiteDB can translate any .NET method call. Mixing domain-logic methods into query predicates.","solutions":["Rewrite the query to use only supported methods and member comparisons (e.g., compare a mapped field directly instead of calling a method).","If the method result is constant relative to the query, hoist it into a closure variable so the visitor evaluates it in memory rather than trying to translate it.","Register a custom ITypeResolver for the type if translation is genuinely needed.","Fall back to a raw BsonExpression or post-query in-memory filtering."],"exampleFix":"// before\nvar active = col.Find(x => x.Status.IsActive());\n// Status has no resolver\n\n// after -- compare a mapped primitive field instead\nvar active = col.Find(x => x.Status == \"Active\");","handlingStrategy":"validation","validationCode":"// Hoist method results that are constant relative to the query into closure variables\nvar computedValue = myCustomObj.DoSomething(); // evaluate in memory\ncol.Find(x => x.Field == computedValue);","typeGuard":null,"tryCatchPattern":"try\n{\n    var results = col.Find(x => x.CustomObj.DoSomething() == true);\n}\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"not available to convert to BsonExpression\"))\n{\n    var val = customObj.DoSomething();\n    results = col.Find(x => x.Field == val);\n}","preventionTips":["Keep custom methods out of LINQ query predicates; compute constant results before the query.","Only use methods on types that have a registered ITypeResolver (String, DateTime, etc.).","If you need custom translation, register a custom ITypeResolver for the type.","Write integration tests for each query predicate to catch unsupported methods early."],"tags":["linq","method-call","resolver"],"backgroundTag":null,"analyzedSha":"f906a5f850678719e39a39a006cb66dcae563cfa","analyzedAt":"2026-08-13T21:56:30.148Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}