{"record":{"id":"00eae556f7c671b2","repo":"stride3d/stride","slug":"converter-i-is-not-null-but-previous-converter-i-1-was-null","errorCode":null,"errorMessage":"Converter{i} is not null but previous Converter{i - 1} was null","messagePattern":"Converter(.+?) is not null but previous Converter(.+?) was null","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation.Avalonia/Converters/Chained.cs","lineNumber":263,"sourceCode":"    }\n\n    /// <inheritdoc/>\n    public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)\n    {\n        var output = value;\n        var conversionEnded = false;\n\n        for (var i = 0; i < MaxConverterCount; ++i)\n        {\n            var input = output;\n            if (converters[i] == null)\n            {\n                conversionEnded = true;\n                continue;\n            }\n\n            if (conversionEnded)\n                throw new InvalidOperationException($\"Converter{i} is not null but previous Converter{i - 1} was null\");\n\n            var type = converterTargetType[i] ?? (i == MaxConverterCount - 1 || converters[i + 1] == null ? targetType : typeof(object));\n            output = converters[i]!.Convert(input, type, converterParameters[i], culture);\n        }\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)","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation.Avalonia/Converters/Chained.cs#L245-L281","documentation":"The Chained value converter applies a fixed-size array of converters in order; a null entry acts as a pass-through and ends the chain. Once a null converter has ended the conversion, any later non-null converter is a configuration error — the chain is ambiguous — so Convert throws this InvalidOperationException.","triggerScenarios":"Declaring a ChainedConverter with ConverterN set but an earlier ConverterN-1 null in XAML (e.g. Converter3 defined while Converter2 is missing). Passing nulls into the converters array via code in a non-prefix layout.","commonSituations":"Copy-pasting converter XAML and forgetting to shift indices; removing an intermediate converter without renumbering; designers binding only Converter0 and Converter2.","solutions":["Renumber the converters so all non-null converters occupy a contiguous prefix starting at Converter0","Set the gaps to null consistently: keep converters 0..k non-null and k+1..Max null","Split into two chained converters instead of leaving a hole","Add a unit/preview check that converters form a prefix sequence before use"],"exampleFix":"<!-- before -->\n<c:Chained Converter=\"{x:Null}\" Converter1=\"{StaticResource convA}\"/>\n<!-- after -->\n<c:Chained Converter=\"{StaticResource identity}\" Converter1=\"{StaticResource convA}\"/>","handlingStrategy":"type-guard","validationCode":"object[] converters = { ch.Converter, ch.Converter1, ch.Converter2 };\nbool valid = converters.Select(c => c != null).TakeWhile(b => b).Count() == converters.Count(c => c != null);","typeGuard":"static bool IsContiguousPrefix(object[] converters) => converters.TakeWhile(c => c != null).Count() == converters.Count(c => c != null);","tryCatchPattern":"try { return chained.Convert(value, targetType, param, culture); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"was null\")) { return Binding.DoNothing; }","preventionTips":["Keep converters contiguous starting at Converter0; null out trailing slots","Review XAML after removing any intermediate converter","Write a design-time/preview check for converter chains","Prefer composing converters in code where nulls are explicit"],"tags":["avalonia","xaml","converter","invalid-configuration"],"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"}