{"record":{"id":"72bf3b354f8a80c2","repo":"dotnet/machinelearning","slug":"value-cannot-be-null-parameter-retainedjoincolu","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'retainedJoinColumnNames')","messagePattern":"Value cannot be null\\. \\(Parameter 'retainedJoinColumnNames'\\)","errorType":"validation","errorClass":"System.ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.Data.Analysis/DataFrame.Join.cs","lineNumber":177,"sourceCode":"        /// <param name=\"other\"></param> \n        /// <param name=\"leftJoinColumn\"></param> \n        /// <param name=\"rightJoinColumn\"></param> \n        /// <param name=\"leftSuffix\"></param> \n        /// <param name=\"rightSuffix\"></param> \n        /// <param name=\"joinAlgorithm\"></param> \n        /// <returns></returns> \n        public DataFrame Merge<TKey>(DataFrame other, string leftJoinColumn, string rightJoinColumn, string leftSuffix = \"_left\", string rightSuffix = \"_right\", JoinAlgorithm joinAlgorithm = JoinAlgorithm.Left)\n        {\n            return Merge(other, new[] { leftJoinColumn }, new[] { rightJoinColumn }, leftSuffix, rightSuffix, joinAlgorithm);\n        }\n\n        private static HashSet<long> Merge(DataFrame retainedDataFrame, DataFrame supplementaryDataFrame,\n            string[] retainedJoinColumnNames, string[] supplemetaryJoinColumnNames,\n            out PrimitiveDataFrameColumn<long> retainedRowIndices, out PrimitiveDataFrameColumn<long> supplementaryRowIndices,\n            bool isInner = false, bool calculateIntersection = false)\n        {\n            if (retainedJoinColumnNames == null)\n                throw new ArgumentNullException(nameof(retainedJoinColumnNames));\n\n            if (supplemetaryJoinColumnNames == null)\n                throw new ArgumentNullException(nameof(supplemetaryJoinColumnNames));\n\n            if (retainedJoinColumnNames.Length != supplemetaryJoinColumnNames.Length)\n                throw new ArgumentException(Strings.MismatchedArrayLengths, nameof(retainedJoinColumnNames));\n\n            Dictionary<long, ICollection<long>> occurrences = GetOccurences(retainedDataFrame, supplementaryDataFrame,\n                retainedJoinColumnNames, supplemetaryJoinColumnNames, out HashSet<long> supplementaryJoinColumnsNullIndices);\n\n            return PerformMerging(retainedDataFrame, retainedJoinColumnNames, occurrences, supplementaryJoinColumnsNullIndices,\n                out retainedRowIndices, out supplementaryRowIndices, isInner, calculateIntersection);\n        }\n\n        private static Dictionary<long, ICollection<long>> GetOccurences(DataFrame retainedDataFrame, DataFrame supplementaryDataFrame,\n            string[] retainedJoinColumnNames, string[] supplemetaryJoinColumnNames, out HashSet<long> supplementaryJoinColumnsNullIndices)\n        {\n            supplementaryJoinColumnsNullIndices = new HashSet<long>();","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.Data.Analysis/DataFrame.Join.cs#L159-L195","documentation":"The private Merge method in DataFrame.Join requires both join-key arrays to be non-null. When retainedJoinColumnNames is null it throws ArgumentNullException(nameof(retainedJoinColumnNames)), producing 'Value cannot be null. (Parameter 'retainedJoinColumnNames')'. The caller (public Merge/Join overloads) must supply the list of column names to join on for the retained DataFrame.","triggerScenarios":"Calling df.Merge(other, null, new[]{\"key\"}) (or a Join overload path) where the left/retained join-column array is null.","commonSituations":"Building join column names dynamically and the array ended up null instead of empty; misreading the Merge API signature and passing null for the left keys; refactoring joined columns away.","solutions":["Pass a non-empty string[] of column names present in the retained DataFrame for retainedJoinColumnNames","Compute the join keys before calling and assert they are not null","Catch ArgumentNullException and surface a clearer domain error in your app","Use the friendlier public Join overloads that derive join columns for you"],"exampleFix":"// before\ndf.Merge(other, null, new[] { \"Id\" });\n// after\ndf.Merge(other, new[] { \"Id\" }, new[] { \"Id\" });","handlingStrategy":"validation","validationCode":"if (leftKeys == null || leftKeys.Length == 0) throw new InvalidOperationException(\"retainedJoinColumnNames required\");","typeGuard":null,"tryCatchPattern":"try { return df.Merge(other, leftKeys, rightKeys); } catch (ArgumentNullException ex) when (ex.ParamName == \"retainedJoinColumnNames\") { throw new ArgumentException(\"Left join keys must be provided\", ex); }","preventionTips":["Never pass null for join-key arrays; use empty checks upstream","Prefer public Join overloads with clearer contracts","Validate key columns exist in the DataFrame before merging"],"tags":["argumentnull","join","dataframe"],"backgroundTag":"null-argument","analyzedSha":"7b76e69cf964daeca3f1377af6bc5543284d56c6","analyzedAt":"2026-09-11T12:35:38.930Z","contentChangedAt":"2026-09-11T12:35:38.930Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}