{"record":{"id":"f9dd5c3ad497039d","repo":"microsoft/garnet","slug":"unable-to-parse-acl-rule-exception-filename-exc","errorCode":null,"errorMessage":"Unable to parse ACL rule {exception.Filename}:{exception.Line}:  {exception.Message}","messagePattern":"Unable to parse ACL rule (.+?):(.+?):  (.+?)","errorType":"exception","errorClass":"ACLException","httpStatus":null,"severity":"error","filePath":"libs/server/ACL/AccessControlList.cs","lineNumber":203,"sourceCode":"\n            try\n            {\n                streamReader = new StreamReader(File.OpenRead(aclConfigurationFile), Encoding.UTF8, true);\n            }\n            catch\n            {\n                throw new ACLException($\"Unable to open ACL configuration file '{aclConfigurationFile}'\");\n            }\n\n            // Remove default user and load statements\n            try\n            {\n                acl._userHandles.Clear();\n                acl.Import(streamReader, aclConfigurationFile);\n            }\n            catch (ACLParsingException exception)\n            {\n                throw new ACLException($\"Unable to parse ACL rule {exception.Filename}:{exception.Line}:  {exception.Message}\");\n            }\n            finally\n            {\n                streamReader.Close();\n            }\n\n            // Add back default user and update the cached default user handle\n            _defaultUserHandle = acl.CreateDefaultUserHandle(defaultPassword);\n\n            // Atomically replace the user list\n            _userHandles = acl._userHandles;\n        }\n\n        /// <summary>\n        /// Save current\n        /// </summary>\n        /// <param name=\"aclConfigurationFile\"></param>\n        public void Save(string aclConfigurationFile)","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/server/ACL/AccessControlList.cs#L185-L221","documentation":"Thrown by AccessControlList.Load() when a line in the ACL configuration file fails to parse. The inner ACLParsingException is rewrapped as an ACLException that includes the filename, the 1-based line number, and the original parser message. The load is atomic: if parsing fails the existing rules are left untouched (the temporary ACL is discarded).","triggerScenarios":"Calling AccessControlList.Load(defaultPassword, aclConfigurationFile) where the file contains a malformed ACL rule line (e.g. 'user default on >password invalidrule', an unrecognized category like '+@nosuchcat', or an unterminated password token). ACLParser.ParseACLRule throws ACLException for each syntax violation, Import() wraps it in ACLParsingException with the line number, and Load() re-throws as ACLException.","commonSituations":"Hand-editing the ACL config file and introducing a typo; upgrading Garnet and using a rule keyword that was renamed or removed; pasting a Redis ACL file that uses a syntax Garnet's parser doesn't support; encoding issues (non-UTF-8 BOM) confusing the tokenizer.","solutions":["Read the full error message: it names the file and the exact line number — open that line and fix the syntax error.","Validate against Garnet's supported ACL rule grammar (user, on/off, >password, +@category, +command, allcommands/nocommands, etc.).","Use the ACL SETUSER command at runtime instead of editing the file directly, then SAVE to persist a known-good file.","If upgrading, check the release notes for ACL grammar changes and migrate affected rules."],"exampleFix":"// before (malformed line in acl.conf):\n//   user default on >secretpass +@all +@nonexistent\n// after:\n//   user default on >secretpass +@all +@read +@write","handlingStrategy":"try-catch","validationCode":"// Validate ACL file is parseable before startup by dry-loading\nif (!File.Exists(aclFile)) throw new FileNotFoundException(aclFile);\nvar lines = File.ReadAllLines(aclFile);\nforeach (var (line, idx) in lines.Select((l, i) => (l, i)))\n{\n    var trimmed = line.Trim();\n    if (trimmed.Length == 0 || trimmed.StartsWith('#')) continue;\n    // ACLParser.ParseACLRule is internal; validate via a staging ACL load instead\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    acl.Load(defaultPassword, aclConfigurationFile);\n}\ncatch (ACLException ex)\n{\n    // ex.Message contains file:line:detail — surface to operator, keep old rules\n    logger.LogError(ex, \"ACL file load failed; retaining previous rules\");\n    throw;\n}","preventionTips":["Use ACL SETUSER + SAVE to generate config files rather than hand-editing.","Validate the ACL file on a staging instance before deploying.","Keep ACL rule syntax within the documented Garnet grammar."],"tags":["acl","config","parsing","startup"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}