{"record":{"id":"656b0e8f2a53c794","repo":"stride3d/stride","slug":"converter-i-is-null-but-following-converter-i-1-is-not-null","errorCode":null,"errorMessage":"Converter{i} is null but following Converter{i + 1} is not null","messagePattern":"Converter(.+?) is null but following Converter(.+?) is not null","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation.Avalonia/Converters/Chained.cs","lineNumber":285,"sourceCode":"        }\n        return output;\n    }\n\n    /// <inheritdoc/>\n    public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)\n    {\n        var output = value;\n\n        var conversionStarted = false;\n\n        for (var i = MaxConverterCount - 1; i >= 0; --i)\n        {\n            var input = output;\n            if (converters[i] == null)\n            {\n                if (!conversionStarted)\n                    continue;\n                throw new InvalidOperationException($\"Converter{i} is null but following Converter{i + 1} is not null\");\n            }\n\n            conversionStarted = true;\n\n            var type = converterTargetType[i] ?? (i == 0 ? targetType : typeof(object));\n            output = converters[i]!.ConvertBack(input, type, converterParameters[i], culture);\n        }\n        return output;\n    }\n}\n","sourceCodeStart":267,"sourceCodeEnd":296,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation.Avalonia/Converters/Chained.cs#L267-L296","documentation":"ChainedConverter.ConvertBack walks the converters in reverse; a null converter before conversion starts is skipped, but once conversion has started, encountering a null converter followed by a non-null one is an invalid chain layout. ConvertBack throws this InvalidOperationException to flag the inconsistent configuration.","triggerScenarios":"A converter chain where ConverterN is null while ConverterN+1 is non-null, exercised on a two-way binding so ConvertBack runs (e.g. Converter0 set, Converter1 null, Converter2 set, and the target writes back to the source).","commonSituations":"One-way bindings set up in XAML that later become TwoWay; the hole in the chain goes unnoticed until an edit triggers ConvertBack; renumbering mistakes after removing a converter.","solutions":["Remove or null out all converters after the gap so non-null converters are contiguous from Converter0","Fill the gap with an appropriate converter (or a pass-through) if the later converter is needed","Mark the binding OneWay to avoid ConvertBack if back-conversion is undesired","Restructure into multiple smaller chained converters without holes"],"exampleFix":"// before\nvar chained = new Chained { Converter = c0, Converter1 = null, Converter2 = c2 };\n// after\nvar chained = new Chained { Converter = c0, Converter1 = passThrough, Converter2 = c2 };","handlingStrategy":"type-guard","validationCode":"object[] converters = { ch.Converter, ch.Converter1, ch.Converter2 };\nif (!IsContiguousPrefix(converters)) throw new InvalidOperationException(\"Converter chain has a null gap\");","typeGuard":"static bool IsContiguousPrefix(object[] converters) => converters.TakeWhile(c => c != null).Count() == converters.Count(c => c != null);","tryCatchPattern":"try { var back = chained.ConvertBack(value, targetType, param, culture); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"following Converter\")) { return Binding.DoNothing; }","preventionTips":["Use OneWay bindings when ConvertBack is not required","Audit two-way bindings for full converter chains","Avoid null holes by renumbering after edits","Cover ConvertBack in converter unit tests"],"tags":["avalonia","xaml","converter","binding"],"backgroundTag":"invalid-config-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}