microsoft/garnet · error · RedisSerializationException

Unable to deserialize RedisOptions object. Unable to convert

Error message

Unable to deserialize RedisOptions object. Unable to convert object of type {typeof(string)} to object of type {optType}. (Line: {lineCount}; Key: {key}; Property: {prop.Name}).

What it means

Thrown by RedisConfigSerializer.Deserialize when a non-array option value cannot be converted from string to the option's underlying type. This is the fallback after TryChangeType fails for scalar options — e.g., providing 'abc' for an integer property. The parser tried TypeDescriptor converters and Convert.ChangeType, all of which failed.

Source

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

                        // Instantiate a new array
                        var elemType = optType.GetElementType();
                        newVal = Array.CreateInstance(elemType, values.Length);

                        // Try deserializing and setting array elements
                        for (var i = 0; i < values.Length; i++)
                        {
                            if (!TryChangeType(values[i], typeof(string), elemType, out var elem))
                                throw new RedisSerializationException(
                                    $"Unable to deserialize {nameof(RedisOptions)} object. Unable to convert object of type {typeof(string)} to object of type {elemType}. (Line: {lineCount}; Key: {key}; Property: {prop.Name}).");


                            ((Array)newVal).SetValue(elem, i);
                        }
                    }
                    else
                    {
                        throw new RedisSerializationException(
                            $"Unable to deserialize {nameof(RedisOptions)} object. Unable to convert object of type {typeof(string)} to object of type {optType}. (Line: {lineCount}; Key: {key}; Property: {prop.Name}).");
                    }
                }

                // Create a new Option<T> object
                var newOpt = Activator.CreateInstance(prop.PropertyType);

                // Set the underlying option value
                var valueProp = prop.PropertyType.GetProperty(nameof(Option<object>.Value));
                valueProp.SetValue(newOpt, newVal);

                // Set the options property to the new option object
                prop.SetValue(options, newOpt);

                // Append usage warning, if defined
                var redisOptionAttr = (RedisOptionAttribute)prop.GetCustomAttributes(typeof(RedisOptionAttribute), false).First();
                if (!string.IsNullOrEmpty(redisOptionAttr.UsageWarning))
                {

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Check the property name and key in the error message to identify the directive.
  2. Provide a value that matches the expected type (e.g., integer for Port, valid boolean or numeric for timeout).
  3. Refer to the GarnetServerOptions property type for the correct value format.

Example fix

// before:
//   port abc

// after:
//   port 6379
Defensive patterns

Strategy: validation

Validate before calling

var propType = typeof(RedisOptions).GetProperty(key)?.PropertyType;
if (propType != null)
{
    var optType = propType.GenericTypeArguments.First();
    var converter = TypeDescriptor.GetConverter(optType);
    if (!converter.IsValid(value))
        throw new FormatException($"Value '{value}' is not valid for type {optType.Name} (key: {key})");
}

Type guard

static bool CanConvertScalar(string value, Type targetType)
{
    var converter = TypeDescriptor.GetConverter(targetType);
    return converter.IsValid(value);
}

Try / catch

try
{
    var redisOpts = RedisConfigSerializer.Deserialize(reader, logger);
}
catch (RedisSerializationException ex) when (ex.Message.Contains("Unable to convert object of type"))
{
    logger.LogError("Redis config value type mismatch: {msg}", ex.Message);
    throw;
}

Prevention

When it happens

Trigger: A config directive whose value is a single scalar that doesn't match the property type. For example, 'port abc' where Port expects an int, or 'timeout true' where the property expects a numeric value.

Common situations: Typographical errors in config files; unit mismatches (e.g., providing '10ms' where a raw integer is expected); locale-related number format issues; using a Redis directive name that maps to a different type than expected.

Related errors


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