{"record":{"id":"a17aea9d6f8c02f6","repo":"dotnet/machinelearning","slug":"not-a-rowtorowmapper","errorCode":null,"errorMessage":"Not a RowToRowMapper.","messagePattern":"Not a RowToRowMapper\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.TimeSeries/SequentialTransformerBase.cs","lineNumber":454,"sourceCode":"            var bs = new BinarySaver(Host, new BinarySaver.Arguments());\n            bs.TryWriteTypeDescription(ctx.Writer.BaseStream, OutputColumnType, out int byteWritten);\n        }\n\n        public abstract DataViewSchema GetOutputSchema(DataViewSchema inputSchema);\n\n        internal abstract IStatefulRowMapper MakeRowMapper(DataViewSchema schema);\n\n        internal SequentialDataTransform MakeDataTransform(IDataView input)\n        {\n            Host.CheckValue(input, nameof(input));\n            return new SequentialDataTransform(Host, this, input, MakeRowMapper(input.Schema));\n        }\n\n        public IDataView Transform(IDataView input) => MakeDataTransform(input);\n\n        public IRowToRowMapper GetRowToRowMapper(DataViewSchema inputSchema)\n        {\n            throw new InvalidOperationException(\"Not a RowToRowMapper.\");\n        }\n\n        IRowToRowMapper IStatefulTransformer.GetStatefulRowToRowMapper(DataViewSchema inputSchema)\n        {\n            Host.CheckValue(inputSchema, nameof(inputSchema));\n            return new TimeSeriesRowToRowMapperTransform(Host, new EmptyDataView(Host, inputSchema), MakeRowMapper(inputSchema));\n        }\n\n        internal virtual IStatefulTransformer Clone() => (SequentialTransformerBase<TInput, TOutput, TState>)MemberwiseClone();\n\n        IStatefulTransformer IStatefulTransformer.Clone() => Clone();\n\n        internal sealed class SequentialDataTransform : TransformBase, ITransformTemplate, IRowToRowMapper\n        {\n            private readonly IStatefulRowMapper _mapper;\n            private readonly SequentialTransformerBase<TInput, TOutput, TState> _parent;\n            private readonly IDataView _transform;\n            private readonly ColumnBindings _bindings;","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.TimeSeries/SequentialTransformerBase.cs#L436-L472","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Do not call GetRowToRowMapper on time-series transformers; instead call Transform(input) to get an IDataView of the transformed data.","If a stateful row-to-row mapper is needed, use IStatefulTransformer.GetStatefulRowToRowMapper (implemented here via TimeSeriesRowToRowMapperTransform) instead.","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.","Guard with a type check (transformer is IRowToRowMapper) before calling, and fall back to Transform."],"exampleFix":"// before\nvar mapper = transformer.GetRowToRowMapper(schema); // throws\n\n// after\nif (transformer is IRowToRowMapper mapper2)\n{\n    var m = mapper2;\n}\nelse\n{\n    var output = transformer.Transform(dataView); // stateful path\n}","handlingStrategy":"try-catch","validationCode":"bool safe = transformer is not IRowToRowMapper && transformer is IStatefulTransformer;","typeGuard":"static bool HasRowToRowMapper(ITransformer t) => t is IRowToRowMapper;","tryCatchPattern":"try { var mapper = transformer.GetRowToRowMapper(schema); }\ncatch (InvalidOperationException ex) when (ex.Message == \"Not a RowToRowMapper.\")\n{ var output = transformer.Transform(dataView); }","preventionTips":["Check transformer capabilities via `is IRowToRowMapper` before mapper-based code paths.","Treat time-series transformers as stateful/terminal pipeline stages.","Use IStatefulTransformer.GetStatefulRowToRowMapper for stateful mappers."],"tags":["dotnet","ml-net","time-series","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"7b76e69cf964daeca3f1377af6bc5543284d56c6","analyzedAt":"2026-09-11T12:35:38.930Z","contentChangedAt":"2026-09-11T12:35:38.930Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}