Csvhelper: Include field name or index in Exception when conversion cannot be performed

Created on 12 Sep 2013  路  15Comments  路  Source: JoshClose/CsvHelper

Please include the field name, index, and/or value in the CsvTypeConverterException object thrown by the default converter. Without this information, it's difficult to debug when using the NuGet package.

CsvHelper.TypeConversion.CsvTypeConverterException: The conversion cannot be performed.
bug

Most helpful comment

Hi there. Many thanks for the library. Would you reconsider putting this information in the standard exception message? Reading CSVs from "the wild" is a trial and error affair because they are often riddled with errors, which means that we constantly get conversion errors dealing with new sheets.

I don't understand the rationale for hiding the essential exception message. I shouldn't have to know to catch a specific exception type - and to deal with a custom property - to get the info that I need.

All 15 comments

Does CsvHelperException.Data["CsvHelper"] give you any more information?

I didn't see it there. I ended up using reflection to transform each field one-by-one so that I could determine which field was causing the problem.

Any reading exceptions that occur should have that information on it. Can you give a small example (or unit test) that reproduces this?

Hi Josh,

Here is an example that reproduces the issue:

``` c#
[TestFixture]
public class Issue192Test
{
public class CsvRecord
{
public DateTime? BreakStart { get; set; }
public DateTime? BreakEnd { get; set; }
}

    public class CsvRecordMap : CsvClassMap<CsvRecord>
    {
        public override void CreateMap()
        {
            Map(m => m.BreakStart).Name("Break Start");
            Map(m => m.BreakEnd).Name("Break End");
        }
    }
    [Test]
    public void TestTypeConverter()
    {
        const string csvData = @"Break Start,Break End

25/08/2013 20:59,25/08/a2013 9:08:00 PM
";
var errors = new List();
var csvConfiguration = new CsvConfiguration
{
SkipEmptyRecords = true,
Delimiter = ",",
CultureInfo = new CultureInfo("en-AU"),
TrimFields = true,
TrimHeaders = true,
HasHeaderRecord = true,
IgnoreReadingExceptions = true,
ReadingExceptionCallback =
(ex, row) => errors.Add(string.Format("Line[{0}]: {1}", row.Row, ex.Message))
};
using (var reader = new CsvReader(new StringReader(csvData), csvConfiguration))
{
reader.Configuration.RegisterClassMap();
var lines = reader.GetRecords().ToList();
}
Console.WriteLine(string.Join(",", errors));
}
}
```

In case it's not obvious, i've added a rogue 'a' character in the datetime of the 'break end' field

If we can somehow get more information out of that exception such as the field name/field index, that would be great.

Thanks for the code to reproduce. I'll look into this.

I believe the issue in the GetRecords() and GetRecords() methods.

In the exception block, you should move the

ExceptionHelper.AddExceptionDataMessage( ex, parser, type, namedIndexes, currentIndex, currentRecord );

call above the

if( configuration.IgnoreReadingExceptions) 

block

If you put a try/catch around reading, you'll get the extra exception info in ex.Data["CsvHelper"]. In your case @paulduran I will need to make that change because it's not there when the callback happens.

Hi there. Many thanks for the library. Would you reconsider putting this information in the standard exception message? Reading CSVs from "the wild" is a trial and error affair because they are often riddled with errors, which means that we constantly get conversion errors dealing with new sheets.

I don't understand the rationale for hiding the essential exception message. I shouldn't have to know to catch a specific exception type - and to deal with a custom property - to get the info that I need.

I would add that current fix has exception text as single message.
There is no way to extract field name, field value etc except trying to parse this text.

In case we need to show to user localized message with which field and value are wrong - there is no choise. All information are in private properties: namedIndexes, currentIndex etc.
This is ugly

@NecroFilja Try the beta. There is a custom CsvHelperException that is thrown that should contain all the info you're looking for. https://github.com/JoshClose/CsvHelper/blob/master/src/CsvHelper/CsvHelperException.cs

Thank you for this great library.
I still see null in e.Data["CsvHelper"] when this exception happens. Any ways to get column name, row number of cell which has the bad data?

That doesn't exist anymore. You'll need to look in CsvHelperException.ReadingContext or CsvHelperException.WritingContext.

I updated to 7.1.1 and when trying to read "double?" (standard type converter)
I have still TypeConverterException (no CsvHelperException). But looks like member info I could now find in exception.MemberMapData

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tdjastrzebski picture tdjastrzebski  路  31Comments

bradmarder picture bradmarder  路  25Comments

Codehhh picture Codehhh  路  15Comments

mmunchandersen picture mmunchandersen  路  27Comments

AdamDotNet picture AdamDotNet  路  29Comments