{"record":{"id":"f82d9bf96651d73f","repo":"DapperLib/Dapper","slug":"the-first-item-in-a-list-expansion-cannot-be-null","errorCode":null,"errorMessage":"The first item in a list-expansion cannot be null","messagePattern":"The first item in a list-expansion cannot be null","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"Dapper/SqlMapper.cs","lineNumber":2197,"sourceCode":"                var count = 0;\r\n                bool isString = value is IEnumerable<string>;\r\n                bool isDbString = value is IEnumerable<DbString>;\r\n                DbType? dbType = null;\r\n\r\n                int splitAt = SqlMapper.Settings.InListStringSplitCount;\r\n                bool viaSplit = splitAt >= 0\r\n                    && TryStringSplit(ref list, splitAt, namePrefix, command, byPosition);\r\n\r\n                if (list is not null && !viaSplit)\r\n                {\r\n                    object? lastValue = null;\r\n                    foreach (var item in list)\r\n                    {\r\n                        if (++count == 1) // first item: fetch some type info\r\n                        {\r\n                            if (item is null)\r\n                            {\r\n                                throw new NotSupportedException(\"The first item in a list-expansion cannot be null\");\r\n                            }\r\n                            if (!isDbString)\r\n                            {\r\n                                dbType = LookupDbType(item.GetType(), \"\", true, out var handler);\r\n                            }\r\n                        }\r\n                        var nextName = namePrefix + count.ToString();\r\n                        if (isDbString && item is DbString str)\r\n                        {\r\n                            str.AddParameter(command, nextName);\r\n                        }\r\n                        else\r\n                        {\r\n                            var listParam = command.CreateParameter();\r\n                            listParam.ParameterName = nextName;\r\n                            if (isString)\r\n                            {\r\n                                listParam.Size = DbString.DefaultLength;\r","sourceCodeStart":2179,"sourceCodeEnd":2215,"githubUrl":"https://github.com/DapperLib/Dapper/blob/72a54c475f75e18cb93cba0809d00a5e6e49efd9/Dapper/SqlMapper.cs#L2179-L2215","documentation":"Thrown by PackListParameters during `IN @list` expansion when the FIRST element of the supplied sequence is null. Dapper inspects the first non-null item to infer the DbType for the generated parameters (it cannot reliably infer a type from null), so a null-first list is rejected with NotSupportedException. Nulls in later positions are handled, but the leading element must not be null.","triggerScenarios":"Passing `new { ids = list }` where `list`'s first element is null, in a `where id in @ids` clause, on a provider whose FeatureSupport.Arrays is false (so Dapper does individual-parameter expansion rather than a TVP). Example: `new[] { null, 1, 2 }`.","commonSituations":"User-supplied filter lists where an empty/null placeholder was prepended; lists built from optional inputs where the first entry was never set; concatenating a null sentinel onto the front of an id list.","solutions":["Filter nulls out of the list before passing it: `ids.Where(x => x.HasValue).Select(x => x.Value)`.","Ensure the first element specifically is non-null (reorder or remove the leading null).","Provide an explicit type by using a DbString/typed list so Dapper does not need to infer from the first item.","If the whole list can be null/empty, branch to a query without the IN clause."],"exampleFix":"// before\nvar ids = new int?[] { null, 1, 2 };\nvar rows = cnn.Query<Foo>(\"select * from Foo where Id in @Ids\", new { Ids = ids });\n// after\nvar ids = new int?[] { null, 1, 2 }.Where(x => x.HasValue).Select(x => x.Value).ToList();\nvar rows = cnn.Query<Foo>(\"select * from Foo where Id in @Ids\", new { Ids = ids });","handlingStrategy":"validation","validationCode":"// Remove nulls (especially a leading null) before IN-expansion.\nvar clean = theList?.Where(x => x is not null).ToList();\nif (clean is null || clean.Count == 0) return Array.Empty<Foo>();\nvar rows = cnn.Query<Foo>(\"select * from Foo where Id in @Ids\", new { Ids = clean });","typeGuard":"static bool FirstItemNotNull(IEnumerable? list) { if (list is null) return true; var e = list.GetEnumerator(); return !e.MoveNext() || e.Current is not null; }","tryCatchPattern":null,"preventionTips":["Filter nulls out of lists used for IN expansion.","Guard empty lists and skip the IN clause entirely.","Use a typed/DbString list so Dapper does not infer type from item 0."],"tags":["dapper","in-expansion","list","null","parameters"],"backgroundTag":null,"analyzedSha":"72a54c475f75e18cb93cba0809d00a5e6e49efd9","analyzedAt":"2026-08-13T14:18:18.115Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}