dotnet/machinelearning · error · ArgumentNullException

columns

Error message

columns

What it means

The private DataViewSchema(Column[]) constructor throws ArgumentNullException("columns") when the columns array is null. The constructor takes ownership of the array and immediately builds the name-to-index dictionary from it, so a null array is rejected. It is documented as callable only from Builder, but reflection or malformed builder state can still reach it.

Source

Thrown at src/Microsoft.ML.DataView/DataViewSchema.cs:450

                for (int i = 0; i < _items.Count; i++)
                    nameMap[_items[i].Name] = i;

                var columns = new Column[_items.Count];
                for (int i = 0; i < columns.Length; i++)
                    columns[i] = new Column(_items[i].Name, i, nameMap[_items[i].Name] != i, _items[i].Type, _items[i].Annotations);

                return new DataViewSchema(columns);
            }
        }

        /// <summary>
        /// This constructor should only be called by <see cref="Builder"/>.
        /// </summary>
        /// <param name="columns">The input columns. The constructed instance takes ownership of the array.</param>
        private DataViewSchema(Column[] columns)
        {
            if (columns == null)
                throw new ArgumentNullException(nameof(columns));

            _columns = columns;
            _nameMap = new Dictionary<string, int>();
            for (int i = 0; i < _columns.Length; i++)
            {
                Debug.Assert(_columns[i].Index == i);
                _nameMap[_columns[i].Name] = i;
            }
        }
    }
}

View on GitHub (pinned to 7b76e69cf9)

Solutions

  1. Construct schemas through Builder.AddColumn + builder.Create(this) instead of the private constructor.
  2. If using reflection, pass a non-empty (or at least non-null, possibly zero-length) Column[] array.
  3. Ensure Builder state is never externally mutated; keep a local reference to the builder and populate it fully.

Example fix

// before
var schema = (DataViewSchema)ctor.Invoke(new object[] { null });
// after
var builder = new DataViewSchema.Builder();
foreach (var (n, t) in cols) builder.AddColumn(n, t);
var schema = builder.Create(null);
Defensive patterns

Strategy: validation

Validate before calling

if (columns == null) throw new ArgumentException("columns array required");

Type guard

bool HasColumns(DataViewSchema.Column[] c) => c != null;

Try / catch

try { var schema = builder.Create(null); } catch (ArgumentNullException) { /* rebuild via Builder */ }

Prevention

When it happens

Trigger: Invoking the private constructor via reflection with null; a Builder whose internal items collection was replaced with null before Create(); custom code copying the constructor pattern.

Common situations: Test harnesses or serializers that reconstruct DataViewSchema instances reflectively; subclassing attempts on Builder that bypass AddColumn/Create.

Related errors


AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11). Data as JSON: /api/errors/92059406859e3652. Report an issue: GitHub.