stride3d/stride · error · InvalidOperationException
Converter is not null but previous Converter was null
Error message
Converter{i} is not null but previous Converter{i - 1} was null What it means
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.
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
Example fix
<!-- before -->
<c:Chained Converter="{x:Null}" Converter1="{StaticResource convA}"/>
<!-- after -->
<c:Chained Converter="{StaticResource identity}" Converter1="{StaticResource convA}"/> Defensive patterns
Strategy: type-guard
Validate before calling
object[] converters = { ch.Converter, ch.Converter1, ch.Converter2 };
bool valid = converters.Select(c => c != null).TakeWhile(b => b).Count() == converters.Count(c => c != null); Type guard
static bool IsContiguousPrefix(object[] converters) => converters.TakeWhile(c => c != null).Count() == converters.Count(c => c != null);
Try / catch
try { return chained.Convert(value, targetType, param, culture); } catch (InvalidOperationException ex) when (ex.Message.Contains("was null")) { return Binding.DoNothing; } Prevention
- 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
When it happens
Trigger: 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.
Common situations: Copy-pasting converter XAML and forgetting to shift indices; removing an intermediate converter without renumbering; designers binding only Converter0 and Converter2.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Converter is null but following Converter is not null
- This behavior must be attached to an instance of…
- The OnComboBoxClosedWithSelectionBehavior must be attached…
- The OnSelectionChangedWithSelectionBehavior must be…
- GameWindow should have either a SwapChainPanel or a…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/00eae556f7c671b2.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation.Avalonia/Converters/Chained.cs:263
}
/// <inheritdoc/>
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
var output = value;
var conversionEnded = false;
for (var i = 0; i < MaxConverterCount; ++i)
{
var input = output;
if (converters[i] == null)
{
conversionEnded = true;
continue;
}
if (conversionEnded)
throw new InvalidOperationException($"Converter{i} is not null but previous Converter{i - 1} was null");
var type = converterTargetType[i] ?? (i == MaxConverterCount - 1 || converters[i + 1] == null ? targetType : typeof(object));
output = converters[i]!.Convert(input, type, converterParameters[i], culture);
}
return output;
}
/// <inheritdoc/>
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
var output = value;
var conversionStarted = false;
for (var i = MaxConverterCount - 1; i >= 0; --i)
{
var input = output;
if (converters[i] == null)View on GitHub (pinned to 96fad776d2)