{"record":{"id":"1ca237ba609ae114","repo":"t8y2/dbx","slug":"etcd-invalid-access-1ca237","errorCode":"ETCD_INVALID_ACCESS","errorMessage":"ETCD_INVALID_ACCESS: access must be READ, WRITE, or READWRITE, got %s","messagePattern":"ETCD_INVALID_ACCESS: access must be READ, WRITE, or READWRITE, got (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/etcd2-go/auth.go","lineNumber":352,"sourceCode":"\t\treturn nil, err\n\t}\n\tif !strings.HasPrefix(key, \"/\") {\n\t\tkey = \"/\" + key\n\t}\n\tpattern := v2PermissionPattern(resource, key)\n\n\tvar accesses []string\n\tif grant {\n\t\taccess := strings.ToUpper(stringOrDefault(params, \"access\", \"\"))\n\t\tswitch access {\n\t\tcase \"READ\":\n\t\t\taccesses = []string{\"read\"}\n\t\tcase \"WRITE\":\n\t\t\taccesses = []string{\"write\"}\n\t\tcase \"READWRITE\":\n\t\t\taccesses = []string{\"read\", \"write\"}\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"ETCD_INVALID_ACCESS: access must be READ, WRITE, or READWRITE, got %s\", access)\n\t\t}\n\t} else {\n\t\taccesses = []string{\"read\", \"write\"}\n\t}\n\n\tctx, cancel := s.beginOperation()\n\tdefer s.endOperation(cancel)\n\tfor _, access := range accesses {\n\t\tdocument := v2Role{Role: role}\n\t\tdirection := v2Permissions{KV: v2RWPermission{}}\n\t\tif access == \"read\" {\n\t\t\tdirection.KV.Read = []string{pattern}\n\t\t} else {\n\t\t\tdirection.KV.Write = []string{pattern}\n\t\t}\n\t\tif grant {\n\t\t\tdocument.Grant = &direction\n\t\t} else {","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/etcd2-go/auth.go#L334-L370","documentation":"authRolePermission validates the optional 'access' parameter against the exact strings READ, WRITE, or READWRITE (defaults to READWRITE when omitted). Any other value is rejected with the coded error ETCD_INVALID_ACCESS before any etcd API call is made. The v2 API internally maps these to the read/write permission lists.","triggerScenarios":"Calling the role permission grant/revoke method (authRolePermission) with access set to something other than 'READ', 'WRITE', or 'READWRITE' — e.g. lowercase 'read', 'rw', or 'readwrite'.","commonSituations":"Passing lowercase values copied from etcd v2 internals ('read'/'write'); abbreviations like 'rw'; client code building the access string dynamically; confusion between v2 per-string permissions and v3 PermType names.","solutions":["Send the access value uppercase: READ, WRITE, or READWRITE","Map lowercase client input to the accepted uppercase forms before the call","Omit the access parameter entirely if READWRITE (the default) is what you want"],"exampleFix":"// before\nagent.call(\"auth role grant\", map[string]any{\"role\": \"r\", \"key\": \"/k\", \"access\": \"read\"})\n\n// after\naccess := strings.ToUpper(\"read\") // \"READ\" | \"WRITE\" | \"READWRITE\"\nagent.call(\"auth role grant\", map[string]any{\"role\": \"r\", \"key\": \"/k\", \"access\": access})","handlingStrategy":"validation","validationCode":"var validAccess = map[string]bool{\"READ\":true,\"WRITE\":true,\"READWRITE\":true}\nfunc validAccessParam(access string) bool { return access == \"\" || validAccess[access] }","typeGuard":null,"tryCatchPattern":"err := grantPermission(role, key, access)\nif err != nil && strings.Contains(err.Error(), \"ETCD_INVALID_ACCESS\") {\n    return fmt.Errorf(\"access %q invalid: use READ, WRITE, or READWRITE\", access)\n}","preventionTips":["Normalize access input with strings.ToUpper and map aliases (rw -> READWRITE) before sending","Define constants for the three legal values instead of raw strings","Omit access when READWRITE (default) is intended"],"tags":["go","etcd","auth","validation","parameter-error"],"backgroundTag":"invalid-parameter-value","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}