dotnet/machinelearning · error · EndOfStreamException

A quoted field opened on line

Error message

A quoted field opened on line {lineNum} was never closed, and we've read to the last line in the file without finding the closing quote

What it means

While reading a CSV/text file with quoted fields, TextLoaderCursor.LineReader keeps reading subsequent lines to find the closing quote of a multi-line quoted field. If the stream ends (ReadLine returns null) before the closing quote is found, it throws EndOfStreamException, meaning the file's quoting is malformed or truncated.

Solutions

  1. Fix the source file so every quoted field is closed, or remove/escape the stray quote character reported on the given line
  2. Re-export or re-download the file completely and verify it is not truncated
  3. Check the TextLoader quoting settings (quoteChar, hasHeader, separator) match the actual file format

Example fix

// before: malformed data
"name,score
alice,1
// after: properly closed quote
"name,score"
alice,1
Defensive patterns

Strategy: validation

Validate before calling

static bool HasBalancedQuotes(string line)
{
    int count = 0;
    foreach (char c in line) if (c == '"') count++;
    return count % 2 == 0;
}

Try / catch

try { data = loader.Load(path); }
catch (EndOfStreamException ex) when (ex.Message.Contains("quoted field"))
{ log.Error("Malformed/truncated CSV: unterminated quoted field", ex); throw new InvalidDataException("Source file has unbalanced quotes", ex); }

Prevention

When it happens

Trigger: Calling LoadFromTextFile / TextLoader on a file where a quote character opens a field on some line (reported as lineNum) and the file ends without the matching closing quote.

Common situations: Truncated downloads or partial file writes; CSV data exported with unbalanced quotes; a stray quote character in data (e.g. an inch mark) that the reader interprets as opening a quoted field; wrong separator/quote-char settings misparsing the file.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.ML.Data/DataLoadSave/Text/TextLoaderCursor.cs:533

                        if (line[0] == '/' && line[1] == '/')
                            return line;
                        if (ignoreHashLine && line[0] == '#')
                            return line;

                        // Get more lines until the last field of the line doesn't contain its newline
                        // inside a quoted field
                        bool lastFieldIncludesNewLine = LastFieldIncludesNewLine(line, false);
                        if (!lastFieldIncludesNewLine)
                            return line;

                        _sb.Clear();
                        _sb.Append(line);
                        while (lastFieldIncludesNewLine)
                        {
                            line = _rdr.ReadLine();

                            if (line == null)
                                throw new EndOfStreamException($"A quoted field opened on line {lineNum} was never closed, and we've read to the last line in the file without finding the closing quote");

                            _sb.Append("\n");
                            _sb.Append(line);
                            lastFieldIncludesNewLine = LastFieldIncludesNewLine(line, true);
                        }

                        return _sb.ToString();
                    }

                    // The startsInsideQuoted parameter indicates if the last field of the previous line
                    // ended in a quoted field which included the newline character,
                    // if it is true, then the beginning of this line is considered to be part
                    // of the last field of the previous line.
                    public bool LastFieldIncludesNewLine(string line, bool startsInsideQuoted = false)
                    {
                        if (line.Length == 0)
                            return startsInsideQuoted;

View on GitHub (pinned to 7b76e69cf9)