{"record":{"id":"12183ef76e239232","repo":"microsoft/garnet","slug":"unable-to-open-acl-configuration-file-aclconfigu","errorCode":null,"errorMessage":"Unable to open ACL configuration file '{aclConfigurationFile}'","messagePattern":"Unable to open ACL configuration file '(.+?)'","errorType":"exception","errorClass":"ACLException","httpStatus":null,"severity":"error","filePath":"libs/server/ACL/AccessControlList.cs","lineNumber":192,"sourceCode":"        public void Load(string defaultPassword, string aclConfigurationFile)\n        {\n            // Attempt to load ACL configuration file\n            if (!File.Exists(aclConfigurationFile))\n            {\n                throw new ACLException($\"Cannot find ACL configuration file '{aclConfigurationFile}'\");\n            }\n\n            // Import file into a new temporary access control list to guarantee atomicity\n            AccessControlList acl = new();\n            StreamReader streamReader;\n\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","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/server/ACL/AccessControlList.cs#L174-L210","documentation":"Thrown by AccessControlList.Load when opening the ACL file with new StreamReader(File.OpenRead(...)) throws any exception. The file exists (the earlier check passed) but could not be opened for reading — typically an IO/permission/sharing error. The original exception is swallowed and rethrown as an ACLException with the path.","triggerScenarios":"The file exists but is locked exclusively by another process/writer; the process lacks read permission; the path is a directory; or an IO error occurs at open time (e.g. removable media not ready).","commonSituations":"The ACL file is being concurrently rewritten by the Save method (which holds a lock on 'this' but not on the OS file across processes); a permissions change between the File.Exists check and OpenRead; antivirus locking the file on Windows; the path is a directory.","solutions":["Ensure the process has read permission on the ACL file.","Avoid concurrent cross-process read/write of the same ACL file, or use a separate atomic rename pattern for writes.","Retry once after a brief delay if the file is likely transiently locked.","Confirm the path is a file, not a directory (File.Exists returns true for files only, but a race could change type)."],"exampleFix":"// before\nacl.Load(defaultPassword, aclFile);\n\n// after\ntry {\n    acl.Load(defaultPassword, aclFile);\n} catch (ACLException ex) when (ex.Message.Contains(\"Unable to open\")) {\n    logger.LogWarning(ex, \"ACL file locked/unreadable, retrying\");\n    Thread.Sleep(100);\n    acl.Load(defaultPassword, aclFile);\n}","handlingStrategy":"retry","validationCode":"try { using var _ = File.OpenRead(aclConfigurationFile); }\ncatch { throw new IOException(\"ACL file cannot be opened for reading.\"); }","typeGuard":"static bool IsReadable(string path)\n{\n    try { using var _ = File.OpenRead(path); return true; } catch { return false; }\n}","tryCatchPattern":"for (int attempt = 0; attempt < 2; attempt++)\n{\n    try { acl.Load(defaultPassword, aclConfigurationFile); break; }\n    catch (ACLException ex) when (attempt == 0 && ex.Message.Contains(\"Unable to open\")) { Thread.Sleep(100); continue; }\n}","preventionTips":["Ensure read permission on the ACL file.","Use atomic temp-file+rename for writes to avoid cross-process locks.","Confirm the path is a file, not a directory.","Briefly retry on transient locks (e.g. antivirus)."],"tags":["acl","configuration","filesystem","io","permissions","file-lock"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}