dotnet/machinelearning · error · ArgumentException

Stream should be non-null and its stream.CanRead property sh

Error message

Stream should be non-null and its stream.CanRead property should be true.

What it means

LoadNumberArrayFromStream requires a readable Stream; it throws ArgumentException when the stream is null or stream.CanRead is false. This is an upfront guard so numeric model data (e.g., tensor weights) can actually be read from the stream.

Source

Thrown at src/Microsoft.ML.TorchSharp/Utils/FileUtils.cs:46

            typeof(double),
        };

        /// <summary>
        /// Load a continuous segment of bytes from stream and parse them into a number array.
        /// NOTE: this function is only for little-endian storage!
        /// </summary>
        /// <typeparam name="T">should be a numeric type</typeparam>
        /// <param name="stream">the stream to read from its current position</param>
        /// <param name="numElements">expected number of parsed numbers</param>
        /// <param name="tSize">number of bytes occupied by the specified type</param>
        /// <exception cref="NotSupportedException">When the generic type T is not a valid numeric type.</exception>
        /// <exception cref="ArgumentException"/>
        /// <exception cref="InvalidDataException">When the contents in the stream don't match the need.</exception>
        public static IEnumerable<T> LoadNumberArrayFromStream<T>(Stream stream, int numElements, int tSize)
        {
            if (stream == null || !stream.CanRead)
            {
                throw new ArgumentException($"Stream should be non-null and its stream.CanRead property should be true.");
            }
            if (!_validTypes.Contains(typeof(T)))
            {
                throw new NotSupportedException($"Type {typeof(T)} not supported in data loading.");
            }

            var numBytesConsumed = numElements * tSize;
            var byteBuffer = new byte[numBytesConsumed];
            var numBytesRead = stream.Read(byteBuffer, 0, numBytesConsumed);
            if (numBytesConsumed != numBytesRead)
            {
                throw new InvalidDataException(
                    $"The number of bytes read from stream is less than expected. Please check the data files.");
            }

            var targetBuffer = new T[numBytesConsumed / tSize];
            Buffer.BlockCopy(byteBuffer, 0, targetBuffer, 0, numBytesConsumed);
            return targetBuffer;

View on GitHub (pinned to 7b76e69cf9)

Solutions

  1. Open the file/stream with read access, e.g. `File.OpenRead(path)` or `new FileStream(path, FileMode.Open, FileAccess.Read)`.
  2. Guard before calling: `if (stream is { CanRead: true }) ...` else re-open or fail fast.
  3. Ensure the stream was not disposed/closed before the call; keep it open for the duration of the load.
  4. Wrap the call in try-catch on ArgumentException to translate it into a user-facing data-loading error.

Example fix

// before
using var stream = new FileStream(path, FileMode.Open, FileAccess.Write);
FileUtils.LoadNumberArrayFromStream<float>(stream, n, 4); // throws

// after
using var stream = File.OpenRead(path);
FileUtils.LoadNumberArrayFromStream<float>(stream, n, 4); // OK
Defensive patterns

Strategy: validation

Validate before calling

if (stream is null || !stream.CanRead)
    throw new ArgumentException("A readable stream is required.", nameof(stream));

Type guard

bool IsReadable(Stream? s) => s is { CanRead: true };

Try / catch

try { var data = FileUtils.LoadNumberArrayFromStream<float>(stream, n, 4); }
catch (ArgumentException ex) { log.LogError(ex, "Stream must be non-null and readable"); throw new ModelLoadException(...); }

Prevention

When it happens

Trigger: Passing a null Stream, a write-only stream (opened with FileAccess.Write), a closed/disposed stream whose CanRead returns false, or a stream wrapped for output (e.g., a File.OpenWrite stream).

Common situations: Opening a file with FileMode.Open/FileAccess.Write by mistake, reusing a stream already consumed and disposed, or passing null when an optional stream was never assigned.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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