{"record":{"id":"8627a2597d53a361","repo":"microsoft/garnet","slug":"unable-to-deserialize-redisoptions-object-unable","errorCode":null,"errorMessage":"Unable to deserialize RedisOptions object. Unable to convert object of type {typeof(string)} to object of type {elemType}. (Line: {lineCount}; Key: {key}; Property: {prop.Name}).","messagePattern":"Unable to deserialize RedisOptions object\\. Unable to convert object of type (.+?) to object of type (.+?)\\. \\(Line: (.+?); Key: (.+?); Property: (.+?)\\)\\.","errorType":"exception","errorClass":"RedisSerializationException","httpStatus":null,"severity":"error","filePath":"libs/host/Configuration/Redis/RedisConfigSerializer.cs","lineNumber":111,"sourceCode":"\n                // Try to deserialize the value\n                if (!TryChangeType(value, typeof(string), optType, out var newVal))\n                {\n                    // If unsuccessful and if underlying option type is an array, try to deserialize array by elements\n                    if (optType.IsArray)\n                    {\n                        // Split the values in the serialized array\n                        var values = value.Split(' ');\n\n                        // Instantiate a new array\n                        var elemType = optType.GetElementType();\n                        newVal = Array.CreateInstance(elemType, values.Length);\n\n                        // Try deserializing and setting array elements\n                        for (var i = 0; i < values.Length; i++)\n                        {\n                            if (!TryChangeType(values[i], typeof(string), elemType, out var elem))\n                                throw new RedisSerializationException(\n                                    $\"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}).\");\n\n\n                            ((Array)newVal).SetValue(elem, i);\n                        }\n                    }\n                    else\n                    {\n                        throw new RedisSerializationException(\n                            $\"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}).\");\n                    }\n                }\n\n                // Create a new Option<T> object\n                var newOpt = Activator.CreateInstance(prop.PropertyType);\n\n                // Set the underlying option value\n                var valueProp = prop.PropertyType.GetProperty(nameof(Option<object>.Value));","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/host/Configuration/Redis/RedisConfigSerializer.cs#L93-L129","documentation":"Thrown by RedisConfigSerializer.Deserialize when an array-typed option's individual element cannot be converted from string to the array's element type. The parser splits the value by spaces and attempts element-wise conversion; if any element fails TryChangeType, this error fires. The message includes line number, key, and property name for diagnosis.","triggerScenarios":"A config line whose value is space-separated tokens intended for an array property, where at least one token cannot convert to the element type. For example, a bind directive with a non-IP value, or a port-array directive with non-numeric tokens.","commonSituations":"Config files with typos in array values (e.g., 'bind 127.0.0.1 abc' where 'abc' isn't a valid IP); locale differences causing decimal separator issues; copying values from a source that used a different delimiter.","solutions":["Check the specific token that failed using the line number and key in the error message.","Correct the malformed array element to match the expected element type.","Ensure all space-separated values in the directive are valid for the property's array element type."],"exampleFix":"// before:\n//   bind 127.0.0.1 notanip\n\n// after:\n//   bind 127.0.0.1 10.0.0.1","handlingStrategy":"validation","validationCode":"// Validate array element values before deserialization by checking the property's expected element type\nvar propType = typeof(RedisOptions).GetProperty(key)?.PropertyType;\nif (propType != null && propType.IsArray)\n{\n    var elemType = propType.GetElementType();\n    var converter = TypeDescriptor.GetConverter(elemType);\n    foreach (var token in value.Split(' '))\n        if (!converter.IsValid(token))\n            throw new FormatException($\"Value '{token}' is not valid for type {elemType.Name}\");\n}","typeGuard":"static bool CanConvertArrayElements(string value, Type elemType)\n{\n    var converter = TypeDescriptor.GetConverter(elemType);\n    return value.Split(' ').All(t => converter.IsValid(t));\n}","tryCatchPattern":"try\n{\n    var redisOpts = RedisConfigSerializer.Deserialize(reader, logger);\n}\ncatch (RedisSerializationException ex) when (ex.Message.Contains(\"Unable to convert object of type\"))\n{\n    logger.LogError(\"Redis config type conversion failed: {msg}\", ex.Message);\n    throw;\n}","preventionTips":["Ensure all space-separated values in array directives match the expected element type.","Double-check IP addresses, numeric values, and boolean strings in config files.","Use TypeDescriptor.GetConverter.IsValid to pre-validate values."],"tags":["redis-config","deserialization","type-conversion","configuration"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}