{"record":{"id":"a462e51bd414855e","repo":"kopia/kopia","slug":"invalid-access-level-v","errorCode":null,"errorMessage":"Invalid access level: %v","messagePattern":"Invalid access level: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/acl/access_level.go","lineNumber":49,"sourceCode":"\tfor k, v := range accessLevelToString {\n\t\tstringToAccessLevel[v] = k\n\t}\n}\n\nfunc (a AccessLevel) String() string {\n\ts, ok := accessLevelToString[a]\n\tif !ok {\n\t\treturn strconv.Itoa(int(a))\n\t}\n\n\treturn s\n}\n\n// MarshalJSON implements json.Marshaler.\nfunc (a AccessLevel) MarshalJSON() ([]byte, error) {\n\tj, ok := accessLevelToString[a]\n\tif !ok {\n\t\treturn nil, errors.Errorf(\"Invalid access level: %v\", a)\n\t}\n\n\t//nolint:wrapcheck\n\treturn json.Marshal(j)\n}\n\n// UnmarshalJSON implements json.Unmarshaler.\nfunc (a *AccessLevel) UnmarshalJSON(b []byte) error {\n\tvar s string\n\n\tif err := json.Unmarshal(b, &s); err != nil {\n\t\treturn errors.Wrap(err, \"error unmarshaling access level\")\n\t}\n\n\t*a = stringToAccessLevel[s]\n\n\treturn nil\n}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/kopia/kopia/blob/82495e54b584c1ef6073c9e1be048f57f8aef078/internal/acl/access_level.go#L31-L67","documentation":"AccessLevel.MarshalJSON looks up the level in accessLevelToString; if the AccessLevel value has no registered string representation, marshaling fails with \"Invalid access level\". This guards against out-of-range or unregistered enum values being serialized into ACL JSON.","triggerScenarios":"Marshaling an AccessLevel that was constructed from an unknown integer/string — e.g. AccessLevel(99) via an unchecked conversion, a value deserialized from corrupt or foreign ACL JSON, or a zero-value AccessLevel when the enum starts at 1 and no default is registered.","commonSituations":"Hand-editing ACL JSON with an unsupported access level string/number; upgrading/downgrading kopia so an old ACL references a level no longer defined; programmatically building ACLs with an invalid level constant.","solutions":["Use only the defined AccessLevel constants (e.g. kopiaacl.Read/Write/FullAccess-style exported levels) rather than raw integers.","Validate the access level before marshaling: keep a map of valid values and check membership.","Re-generate the ACL with a supported level via the kopia ACL commands/API.","If data came from another version, migrate the stored ACL to current enum values."],"exampleFix":"// before\nlvl := acl.AccessLevel(7)\ndata, err := json.Marshal(lvl) // \"Invalid access level: 7\"\n// after\nlvl := acl.AccessLevelRead // use a defined constant\nif _, ok := acl.AccessLevelToString[lvl]; !ok {\n    return fmt.Errorf(\"unsupported access level %v\", lvl)\n}\ndata, err := json.Marshal(lvl)","handlingStrategy":"validation","validationCode":"func validAccessLevel(l acl.AccessLevel, known map[acl.AccessLevel]string) bool {\n    _, ok := known[l]\n    return ok\n}\n// check before json.Marshal(lvl)","typeGuard":"func isKnownAccessLevel(l acl.AccessLevel, known map[acl.AccessLevel]string) bool {\n    _, ok := known[l]\n    return ok\n}","tryCatchPattern":"data, err := json.Marshal(aclEntry)\nif err != nil && strings.Contains(err.Error(), \"Invalid access level\") {\n    return fmt.Errorf(\"access level %v not supported; use a defined constant: %w\", lvl, err)\n}","preventionTips":["Only use exported AccessLevel constants; never cast raw ints/strings to AccessLevel.","Validate ACL JSON input against known levels before storing it.","Migrate ACL data when upgrading across versions that changed the enum."],"tags":["acl","enum","marshal"],"backgroundTag":"invalid-enum-value","analyzedSha":"82495e54b584c1ef6073c9e1be048f57f8aef078","analyzedAt":"2026-09-07T20:35:21.689Z","contentChangedAt":"2026-09-07T20:35:21.689Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}