dotnet/machinelearning · error · InvalidOperationException

Not a RowToRowMapper.

Error message

Not a RowToRowMapper.

What it means

SequentialTransformerBase (used by time-series transforms like SSA and anomaly detectors) is a stateful, schema-dependent transformer: its output depends on accumulated input history, not just per-row math. Therefore it cannot provide an IRowToRowMapper, and GetRowToRowMapper always throws this InvalidOperationException. Callers that require a composable row-to-row mapper (e.g. certain pipeline internals) cannot use this transformer directly.

Source

Thrown at src/Microsoft.ML.TimeSeries/SequentialTransformerBase.cs:454

            var bs = new BinarySaver(Host, new BinarySaver.Arguments());
            bs.TryWriteTypeDescription(ctx.Writer.BaseStream, OutputColumnType, out int byteWritten);
        }

        public abstract DataViewSchema GetOutputSchema(DataViewSchema inputSchema);

        internal abstract IStatefulRowMapper MakeRowMapper(DataViewSchema schema);

        internal SequentialDataTransform MakeDataTransform(IDataView input)
        {
            Host.CheckValue(input, nameof(input));
            return new SequentialDataTransform(Host, this, input, MakeRowMapper(input.Schema));
        }

        public IDataView Transform(IDataView input) => MakeDataTransform(input);

        public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema)
        {
            throw new InvalidOperationException("Not a RowToRowMapper.");
        }

        IRowToRowMapper IStatefulTransformer.GetStatefulRowToRowMapper(DataViewSchema inputSchema)
        {
            Host.CheckValue(inputSchema, nameof(inputSchema));
            return new TimeSeriesRowToRowMapperTransform(Host, new EmptyDataView(Host, inputSchema), MakeRowMapper(inputSchema));
        }

        internal virtual IStatefulTransformer Clone() => (SequentialTransformerBase<TInput, TOutput, TState>)MemberwiseClone();

        IStatefulTransformer IStatefulTransformer.Clone() => Clone();

        internal sealed class SequentialDataTransform : TransformBase, ITransformTemplate, IRowToRowMapper
        {
            private readonly IStatefulRowMapper _mapper;
            private readonly SequentialTransformerBase<TInput, TOutput, TState> _parent;
            private readonly IDataView _transform;
            private readonly ColumnBindings _bindings;

View on GitHub (pinned to 7b76e69cf9)

Solutions

  1. Do not call GetRowToRowMapper on time-series transformers; instead call Transform(input) to get an IDataView of the transformed data.
  2. If a stateful row-to-row mapper is needed, use IStatefulTransformer.GetStatefulRowToRowMapper (implemented here via TimeSeriesRowToRowMapperTransform) instead.
  3. Restructure the pipeline so the time-series stage is a terminal/forecasting step, and only row-to-row-friendly transformers are exposed to mapper-based code paths.
  4. Guard with a type check (transformer is IRowToRowMapper) before calling, and fall back to Transform.

Example fix

// before
var mapper = transformer.GetRowToRowMapper(schema); // throws

// after
if (transformer is IRowToRowMapper mapper2)
{
    var m = mapper2;
}
else
{
    var output = transformer.Transform(dataView); // stateful path
}
Defensive patterns

Strategy: try-catch

Validate before calling

bool safe = transformer is not IRowToRowMapper && transformer is IStatefulTransformer;

Type guard

static bool HasRowToRowMapper(ITransformer t) => t is IRowToRowMapper;

Try / catch

try { var mapper = transformer.GetRowToRowMapper(schema); }
catch (InvalidOperationException ex) when (ex.Message == "Not a RowToRowMapper.")
{ var output = transformer.Transform(dataView); }

Prevention

When it happens

Trigger: Calling GetRowToRowMapper(inputSchema) on any Microsoft.ML.TimeSeries transformer deriving from SequentialTransformerBase (e.g. SsaForecasting, SrCnnEntireAnomalyDetector) or on an EstimatorChain/transform that internally contains one, typically via ITransformer.GetRowToRowMapper or ML.NET's 'transform as mapper' code paths.

Common situations: Tooling that generically calls GetRowToRowMapper to inspect or cache per-row transforms; pipelines that try to prune/compose mappers over a time-series forecasting model; code written for row-to-row transformers being reused with time-series transformers.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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