{"record":{"id":"df2b4def3a461967","repo":"microsoft/garnet","slug":"unable-to-deserialize-redisoptions-object-line-l","errorCode":null,"errorMessage":"Unable to deserialize RedisOptions object. Line {lineCount} not in expected format (keyword argument1 argument2 ... argumentN).","messagePattern":"Unable to deserialize RedisOptions object\\. Line (.+?) not in expected format \\(keyword argument1 argument2 \\.\\.\\. argumentN\\)\\.","errorType":"exception","errorClass":"RedisSerializationException","httpStatus":null,"severity":"error","filePath":"libs/host/Configuration/Redis/RedisConfigSerializer.cs","lineNumber":77,"sourceCode":"        /// <exception cref=\"RedisSerializationException\"></exception>\n        public static RedisOptions Deserialize(StreamReader reader, ILogger logger)\n        {\n            var options = new RedisOptions();\n\n            int lineCount = 0;\n            string line;\n            while ((line = reader.ReadLine()) != null)\n            {\n                lineCount++;\n\n                // Ignore whitespaces and comments\n                if (string.IsNullOrWhiteSpace(line) || line.TrimStart().StartsWith('#'))\n                    continue;\n\n                // Expected line format: keyword argument1 argument2 ... argumentN\n                var sepIdx = line.IndexOf(' ');\n                if (sepIdx == -1)\n                    throw new RedisSerializationException(\n                        $\"Unable to deserialize {nameof(RedisOptions)} object. Line {lineCount} not in expected format (keyword argument1 argument2 ... argumentN).\");\n\n                // Ignore key when no matching property found \n                var key = line.Substring(0, sepIdx);\n                if (!KeyToProperty.Value.ContainsKey(key))\n                {\n                    logger?.LogWarning(\"Redis configuration option not supported: {key}.\", key);\n                    continue;\n                }\n\n                var value = line.Substring(sepIdx + 1);\n\n                // Get matching property & the underlying option type (T in Option<T>)\n                var prop = KeyToProperty.Value[key];\n                var optType = prop.PropertyType.GenericTypeArguments.First();\n\n                // Try to deserialize the value\n                if (!TryChangeType(value, typeof(string), optType, out var newVal))","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/host/Configuration/Redis/RedisConfigSerializer.cs#L59-L95","documentation":"Thrown by RedisConfigSerializer.Deserialize when a non-comment, non-blank line in a Redis-format config file has no space character. Every directive in a Redis .conf file must follow 'keyword argument1 argument2 ... argumentN'. A line with only a keyword and no arguments (no space) is rejected because the parser cannot extract a value portion.","triggerScenarios":"Loading a redis.conf-style file where a directive line is a single bare token with no space separator (e.g., a line containing only 'save' with no arguments). The code at line 75-76 uses IndexOf(' '); -1 means no space was found.","commonSituations":"Hand-edited Redis config files where a user accidentally deleted the argument portion; copy-paste from documentation that truncated the example; config generation tool that emitted keyword-only lines for boolean directives.","solutions":["Inspect the line number reported in the error message and add the missing argument(s) after the keyword.","If the directive genuinely takes no arguments, add a dummy value or remove the line if it's not needed.","Validate the config file format: each non-comment line must contain at least one space separating the keyword from its value."],"exampleFix":"// before (line 3 of config file):\n//   save\n\n// after:\n//   save 3600 1 300 100 60 10000","handlingStrategy":"validation","validationCode":"foreach (var (line, num) in File.ReadLines(configPath).Select((l, i) => (l, i + 1)))\n{\n    var trimmed = line.TrimStart();\n    if (string.IsNullOrWhiteSpace(trimmed) || trimmed.StartsWith('#')) continue;\n    if (!line.Contains(' '))\n        throw new FormatException($\"Line {num}: directive '{trimmed}' has no arguments (expected 'keyword arg1 ...')\");\n}","typeGuard":"static bool IsValidConfigLine(string line)\n{\n    var t = line.TrimStart();\n    if (string.IsNullOrWhiteSpace(t) || t.StartsWith('#')) return true;\n    return line.Contains(' ');\n}","tryCatchPattern":"try\n{\n    var redisOpts = RedisConfigSerializer.Deserialize(reader, logger);\n}\ncatch (RedisSerializationException ex) when (ex.Message.Contains(\"not in expected format\"))\n{\n    logger.LogError(\"Redis config file has a malformed line: {msg}\", ex.Message);\n    throw;\n}","preventionTips":["Every directive line in a Redis config file must have at least one space after the keyword.","Validate config files with a linting tool before deploying.","Use comments starting with '#' for notes instead of bare keywords."],"tags":["redis-config","deserialization","configuration","file-parsing"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}