microsoft/garnet · error · ACLUnknownOperationException
{op}
Error message
{op} What it means
Thrown by ACLParser.ApplyACLOpToUser when an operation token matches none of the recognized forms (ON/OFF/NOPASS/RESET/RESETPASS, >/</#/!, +/-@category, +/-command, ~*/ALLKEYS, RESETKEYS). Any other token is reported verbatim via ACLUnknownOperationException. This is the catch-all for completely unrecognized ACL operations.
Source
Thrown at libs/server/ACL/ACLParser.cs:270
else
{
throw new AclCommandDoesNotExistException(commandName);
}
}
else if (op.Equals("~*", StringComparison.Ordinal) || op.Equals("ALLKEYS", StringComparison.OrdinalIgnoreCase))
{
// NOTE: No-op, because only wildcard key patterns are currently supported. If per-key key
// patterns are ever added, the GET scatter-gather fast path (NetworkGET_SG) must re-check
// ACL per key: it serves GETs past the first without returning through the per-command ACL
// check in ProcessMessages, which is only safe while key access is all-or-nothing.
}
else if (op.Equals("RESETKEYS", StringComparison.OrdinalIgnoreCase))
{
// NOTE: No-op, because only wildcard key patterns are currently supported
}
else
{
throw new ACLUnknownOperationException(op);
}
// There's some fixup that has to be done when parsing a command
static bool TryParseCommandForAcl(string commandName, out RespCommand command)
{
int subCommandSepIx = commandName.IndexOf('|');
bool isSubCommand = subCommandSepIx != -1;
string effectiveName = isSubCommand ? commandName[..subCommandSepIx] + "_" + commandName[(subCommandSepIx + 1)..] : commandName;
if (!Enum.TryParse(effectiveName, ignoreCase: true, out command) || !IsValidParse(command, effectiveName))
{
// Try replacing dots with empty strings for commands like RI.CREATE -> RICREATE
string dotlessName = effectiveName.Replace(".", "");
if (dotlessName != effectiveName && Enum.TryParse(dotlessName, ignoreCase: true, out command) && IsValidParse(command, dotlessName))
{
// Successfully parsed after removing dots — fall through to validation below
}View on GitHub (pinned to 951b0fc683)
Solutions
- Check the token against the supported operation set in ApplyACLOpToUser.
- Prefix passwords with '>'/'<' and hashes with '#'/!' rather than leaving them bare.
- Use categories (+@all / -@dangerous) instead of unsupported 'allcommands'.
- Remove any operation Garnet does not support rather than leaving an unrecognized token.
Example fix
// before
ACLParser.ParseACLRule("user alice on allcommands secret");
// after
ACLParser.ParseACLRule("user alice on +@all >secret"); Defensive patterns
Strategy: validation
Validate before calling
var supported = new HashSet<string>(StringComparer.OrdinalIgnoreCase){"on","off","nopass","reset","resetpass","allkeys","resetkeys"};
// plus prefixed forms >, <, #, !, +, -, +@, -@, ~*
if (!(supported.Contains(op) || ">/</#/!/+/-(+@/-@/~*)".Any(p => op.StartsWith(p))))
throw new ArgumentException($"Unsupported ACL operation: {op}"); Type guard
static bool IsSupportedOp(string op) =>
op.Length>0 && (op[0]=='>'||op[0]=='<'||op[0]=='#'||op[0]=='!'||op[0]=='+'||op[0]=='-'||
op.Equals("on",StringComparison.OrdinalIgnoreCase)||op.Equals("off",StringComparison.OrdinalIgnoreCase)||
op.Equals("allkeys",StringComparison.OrdinalIgnoreCase)||op.Equals("resetkeys",StringComparison.OrdinalIgnoreCase)||
op.Equals("nopass",StringComparison.OrdinalIgnoreCase)||op.Equals("reset",StringComparison.OrdinalIgnoreCase)||
op.Equals("resetpass",StringComparison.OrdinalIgnoreCase)); Try / catch
try { ACLParser.ParseACLRule(line, acl); }
catch (ACLUnknownOperationException ex) { logger.LogError("Unknown op: {Op}", ex.Message); } Prevention
- Prefix passwords with '>' and hashes with '#'.
- Use +@/-@ categories instead of unsupported 'allcommands'.
- Drop operations Garnet does not implement rather than leaving stray tokens.
When it happens
Trigger: A typo such as 'oNn' (close to but not 'on'), a stray token like 'allcommands' (Garnet does not support that; categories are used instead), or a value without an operator prefix (e.g. a bare password 'secret' instead of '>secret').
Common situations: Copy-pasting Redis ACL syntax that Garnet does not implement (e.g. 'allchannels', 'resetchannels', '>&' no-password rules); a delimiter issue leaving a fragment as its own token; hand-editing that introduced a typo.
Related errors
- Malformed ACL rule
- ACL rules need to start with the USER keyword
- {categoryName}
- {commandName}
- {exception.Message}
AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13).
Data as JSON: /api/errors/c89f114100530186.
Report an issue: GitHub.