restsharp/RestSharp · error · InvalidOperationException

If the type implements IEnumerable<T>, then it must contain

Error message

If the type implements IEnumerable<T>, then it must contain a public "Add(T)" method.

What it means

Thrown by CsvHelperSerializer.Deserialize when the target type T implements IEnumerable<T> but does not expose a public 'Add(T)' method. After creating an instance the deserializer reflects for an Add method to populate each record; interfaces like IEnumerable<T> or arrays have no usable Add. Re-wrapped in DeserializationException at line 62.

Source

Thrown at src/RestSharp.Serializers.CsvHelper/CsvHelperSerializer.cs:51

            if (@interface == null) {
                csvReader.Read();
                return csvReader.GetRecord<T>();
            }

            var itemType = @interface.GenericTypeArguments[0];
            T   result;

            try {
                result = Activator.CreateInstance<T>();
            }
            catch (MissingMethodException) {
                throw new InvalidOperationException(message: "The type must contain a public, parameterless constructor.");
            }

            var method = typeof(T).GetMethod(name: "Add");

            if (method == null) {
                throw new InvalidOperationException(
                    message: "If the type implements IEnumerable<T>, then it must contain a public \"Add(T)\" method."
                );
            }

            foreach (var record in csvReader.GetRecords(itemType)) {
                method.Invoke(result, [record]);
            }

            return result;
        }
        catch (Exception exception) {
            throw new DeserializationException(response, exception);
        }
    }

    public string? Serialize(Parameter parameter) => Serialize(parameter.Value);

    public string? Serialize(object? obj) {

View on GitHub (pinned to 6a50821692)

Solutions

  1. Deserialize into List<T> (or another concrete collection with a public Add(T) method).
  2. If the type must be a custom collection, ensure it exposes a public Add(T) method.
  3. Avoid arrays and read-only interfaces as the deserialization target.

Example fix

// before
var data = await client.GetAsync<Foo[]>(request);

// after
var data = await client.GetAsync<List<Foo>>(request);
Defensive patterns

Strategy: validation

Validate before calling

var addMethod = typeof(T).GetMethod("Add");
if (typeof(T).GetInterface("IEnumerable`1") != null && addMethod == null) throw new InvalidOperationException($"{typeof(T)} needs a public Add(T) method");

Type guard

static bool IsCsvAddable<T>() => typeof(T).GetInterface("IEnumerable`1") == null || typeof(T).GetMethod("Add") != null;

Try / catch

try { var data = client.GetAsync<List<T>>(req); } catch (DeserializationException ex) when (ex.InnerException?.Message.Contains("\"Add(T)\" method") == true) { /* switch to List<T> */ }

Prevention

When it happens

Trigger: Deserializing into an array (Foo[]), a read-only collection, a type that implements IEnumerable<T> purely for querying but not for mutation, or into an interface type that has no Add method.

Common situations: Target type is an array T[]; target is IReadOnlyList<T>; target is a custom type implementing IEnumerable<T> without an Add method.

Related errors


AI-assisted analysis of restsharp/RestSharp@6a50821692 (2026-08-13). Data as JSON: /api/errors/44314a8562bb26ea. Report an issue: GitHub.