microsoft/garnet · critical · RedisSerializationException

Unable to convert property {prop.Name} in {typeof(RedisOptio

Error message

Unable to convert property {prop.Name} in {typeof(RedisOptions)} to property {redisOptionAttr.GarnetOptionName} in {typeof(Options)}.

What it means

Thrown by RedisConfigSerializer.TryPopulateOptions when a RedisOptions property and its corresponding Options property have different types, no custom transformer is specified, and TryChangeType fails to convert between them. This indicates a type mapping gap in the framework's option-population logic.

Source

Thrown at libs/host/Configuration/Redis/RedisConfigSerializer.cs:231

                if (redisOptionAttr.GarnetCustomTransformer != null)
                {
                    var parameters = new[] { srcOptValue, null, null };
                    var result = (bool?)typeof(RedisConfigSerializer).GetMethod(nameof(TryApplyTransform), BindingFlags.NonPublic | BindingFlags.Static)
                        ?.MakeGenericMethod(srcOptValueType, dstPropType, redisOptionAttr.GarnetCustomTransformer)
                        .Invoke(null, parameters);
                    dstValue = parameters[1];

                    if (!result.HasValue || !result.Value)
                    {
                        throw new RedisSerializationException((string)parameters[2]);
                    }
                }
                // Try to convert to destination type
                else if (srcOptValueType != dstPropType)
                {
                    if (!TryChangeType(srcOptValue, srcOptValueType, dstPropType, out dstValue))
                    {
                        throw new RedisSerializationException(
                            $"Unable to convert property {prop.Name} in {typeof(RedisOptions)} to property {redisOptionAttr.GarnetOptionName} in {typeof(Options)}.");
                    }
                }
                // Source and destination types are the same with no transformer specified
                else
                {
                    dstValue = srcOptValue;
                }

                // Set the destination property with the converted value
                dstProp.SetValue(options, dstValue);
            }

            return true;
        }

        /// <summary>
        /// Tries to apply a custom IGarnetCustomTransformer to transform a RedisOptions property to an Options property

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Add a GarnetCustomTransformer to the RedisOptionAttribute that handles the type conversion.
  2. Align the types of the RedisOptions property and Options property.
  3. Ensure all assemblies are from the same build to avoid type drift.

Example fix

// before: RedisOptions.Timeout is string, Options.Timeout is TimeSpan, no transformer

// after: add a transformer
//   [RedisOption(Key = "timeout", GarnetOptionName = "Timeout",
//       GarnetCustomTransformer = typeof(StringToTimeSpanTransformer))]
//   public Option<string> Timeout { get; set; }
Defensive patterns

Strategy: validation

Validate before calling

// Check type convertibility between RedisOptions and Options property types
var srcType = typeof(RedisOptions).GetProperty(propName).PropertyType.GenericTypeArguments.First();
var dstType = typeof(Options).GetProperty(dstPropName).PropertyType;
if (srcType != dstType)
{
    var converter = TypeDescriptor.GetConverter(srcType);
    if (!converter.CanConvertTo(dstType) && !TypeDescriptor.GetConverter(dstType).CanConvertFrom(srcType))
        throw new InvalidOperationException($"No conversion path from {srcType.Name} to {dstType.Name} for {propName}");
}

Prevention

When it happens

Trigger: During TryPopulateOptions, the source property type (from RedisOptions) and destination property type (from Options) differ, no GarnetCustomTransformer is set on the attribute, and the value cannot be converted via TypeDescriptor or Convert.ChangeType.

Common situations: Modifying a RedisOptions or Options property type without adding a custom transformer; framework version mismatch where a property type was changed in one assembly but not the other.

Related errors


AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13). Data as JSON: /api/errors/f4241b5b90cb0641. Report an issue: GitHub.