dotnet/efcore · error · InvalidOperationException
Couldn't find single Add method on type
Error message
Couldn't find single Add method on type '{type.Name}', required for list initializer What it means
Thrown when the translator tries to build a collection initializer (e.g. `new List<int> { 1, 2, 3 }`) but cannot find exactly one Add method with a single parameter on the created type via SingleOrDefault. This happens when the type has zero Add methods (not a collection), or has multiple Add(T) overloads making SingleOrDefault throw — note the code uses SingleOrDefault which returns null for zero matches but throws InvalidOperationException for multiple matches. The null-check then throws the documented error.
Solutions
- For dictionaries: create and populate the dictionary outside the precompiled query body and capture it as a variable, since the TODO comment confirms dictionary initializers are unsupported.
- For custom collections with multiple Add overloads: reduce to a single Add(T) method or create the collection outside the query.
- For non-collection types: don't use collection-initializer syntax — construct and populate via explicit method calls outside the query.
- Use List<T> or arrays instead of specialized collection types inside precompiled queries.
- If a collection must be built in-query, use Enumerable.Range/Repeat/Empty factory methods instead of initializer syntax.
Example fix
// before — dictionary initializer inside query
var query = ctx.Rules.Select(r => new Dictionary<int, string> { { r.Id, r.Name } });
// after — build outside query, or use a different pattern
var map = ctx.Rules.ToDictionary(r => r.Id, r => r.Name); Defensive patterns
Strategy: validation
Validate before calling
// Before precompiling, check collection initializers for Add method ambiguity
foreach (var objCreation in querySyntaxTree.DescendantNodes().OfType<ObjectCreationExpressionSyntax>())
{
if (objCreation.Initializer?.Expressions is null or [] or [AssignmentExpressionSyntax, ..]) continue;
// This is a collection initializer path
var type = semanticModel.GetSymbolInfo(objCreation).Symbol is IMethodSymbol ctor
? ResolveTypeForCheck(ctor.ContainingType) : null;
if (type is null) continue;
var addMethods = type.GetMethods().Where(m => m.Name == "Add" && m.GetParameters().Length == 1).ToList();
if (addMethods.Count != 1)
ReportError($"Type '{type.Name}' has {addMethods.Count} single-param Add methods — collection initializer unsupported");
} Prevention
- Avoid dictionary initializers (new Dictionary<K,V> { { k, v } }) inside precompiled queries — build dictionaries outside.
- Use List<T> or arrays instead of custom or complex collection types.
- Ensure custom collections have exactly one single-parameter Add method.
- Prefer Enumerable factory methods (Enumerable.Range, Repeat, Empty) over collection initializers in queries.
- Build collections outside the precompiled query body and capture them as variables.
When it happens
Trigger: A precompiled query creates a collection with an element initializer where: the type has no single-parameter Add method (not IEnumerable-compatible), the type has multiple single-parameter Add overloads (e.g. a custom collection with Add(int), Add(string) where the element type is ambiguous), or the type is a dictionary with Add(key, value) (two parameters, so no single-param match). SingleOrDefault throws on ambiguity before the null check.
Common situations: Creating dictionaries with collection initializers inside precompiled queries (`new Dictionary<int,string> { { 1, "a" } }` — Add has 2 params); custom collection types with multiple Add overloads; creating types that look like collections but lack a standard Add method; initializing HashSet with complex element types where the Add method has optional parameters creating multiple single-param signatures.
Related errors
- ObjectCreation: Missing constructor
- Invocation: couldn't find method
- Invocation: Found matches for generic method
- MemberAccess: couldn't find member
- ObjectCreation: couldn't find IMethodSymbol for constructor
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/be9375e7f6adffd4.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs:882
_ => throw new InvalidOperationException(
$"ObjectCreation: unsupported initializer for member of type '{lValueSymbol?.GetType().Name}': {e}")
};
return memberInfo is null
? throw new InvalidOperationException(
$"ObjectCreation: couldn't find initialized member '{lValueSymbol.Name}': {e}")
: Bind(memberInfo, Visit(value));
}));
// Non-assignment initializer => list initializer (new List<int> { 1, 2, 3 })
default:
// Find the correct Add() method on the collection type
// TODO: This doesn't work if there are multiple Add() methods (contrived). Complete solution would be to find the base
// TODO: type for all initializer expressions and find an Add overload of that type (or a superclass thereof)
var addMethod = type.GetMethods().SingleOrDefault(m => m.Name == "Add" && m.GetParameters().Length == 1);
if (addMethod is null)
{
throw new InvalidOperationException(
$"Couldn't find single Add method on type '{type.Name}', required for list initializer");
}
// TODO: Dictionary initializer, where each ElementInit has more than one expression
return ListInit(
newExpression,
objectCreation.Initializer.Expressions.Select(e => ElementInit(addMethod, Visit(e))));
}
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override Expression VisitParenthesizedExpression(ParenthesizedExpressionSyntax parenthesized)View on GitHub (pinned to 3a2006ef56)