{"id":"683f5ba50aacbf99","repo":"go-redis/redis","slug":"redis-json-set-mode-must-be-nx-or-xx","errorCode":null,"errorMessage":"redis: JSON.SET mode must be NX or XX","messagePattern":"redis: JSON\\.SET mode must be NX or XX","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"json.go","lineNumber":648,"sourceCode":"func (c cmdable) JSONSetWithArgs(ctx context.Context, key, path string, value interface{}, options *JSONSetArgsOptions) *StatusCmd {\n\tvar bytes []byte\n\tvar err error\n\tswitch v := value.(type) {\n\tcase string:\n\t\tbytes = []byte(v)\n\tcase []byte:\n\t\tbytes = v\n\tdefault:\n\t\tbytes, err = json.Marshal(v)\n\t}\n\targs := []interface{}{\"JSON.SET\", key, path, util.BytesToString(bytes)}\n\tif options != nil {\n\t\tif options.Mode != \"\" {\n\t\t\tswitch strings.ToUpper(options.Mode) {\n\t\t\tcase \"XX\", \"NX\":\n\t\t\t\targs = append(args, strings.ToUpper(options.Mode))\n\t\t\tdefault:\n\t\t\t\tpanic(\"redis: JSON.SET mode must be NX or XX\")\n\t\t\t}\n\t\t}\n\t\tif options.FPHA != \"\" {\n\t\t\targs = append(args, \"FPHA\", string(options.FPHA))\n\t\t}\n\t}\n\tcmd := NewStatusCmd(ctx, args...)\n\tif err != nil {\n\t\tcmd.SetErr(err)\n\t} else {\n\t\t_ = c(ctx, cmd)\n\t}\n\treturn cmd\n}\n\n// JSONStrAppend appends the JSON-string values to the string at the specified path.\n// For more information, see https://redis.io/commands/json.strappend\nfunc (c cmdable) JSONStrAppend(ctx context.Context, key, path, value string) *IntPointerSliceCmd {","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/json.go#L630-L666","documentation":"JSONSetWithArgs panics when options.Mode is a non-empty string other than 'NX' or 'XX' (matched case-insensitively after strings.ToUpper). JSON.SET only accepts NX (set if missing) or XX (set if exists) as its mode flag, so any other value is a programmer error and is rejected up front rather than sent to the server.","triggerScenarios":"Calling JSONSetMode/JSONSetWithArgs with mode = \"SET\", \"EX\", \"XXNX\", or any string that is not NX/XX.","commonSituations":"Confusing JSON.SET mode with SET option flags (EX/PX/EXAT), passing a lower-level SET mode, or a typo like \"NX \" with trailing whitespace that is not stripped.","solutions":["Pass only \"NX\" or \"XX\" (any case) as the mode, or empty string to omit the flag.","Validate user-supplied mode against {\"\", \"NX\", \"XX\"} before calling JSONSetWithArgs.","Use JSONSet (no mode) when no conditional flag is needed."],"exampleFix":"// before\nclient.JSONSetWithArgs(ctx, key, \"$\", v, &redis.JSONSetArgsOptions{Mode: \"EX\"})\n\n// after\nclient.JSONSetWithArgs(ctx, key, \"$\", v, &redis.JSONSetArgsOptions{Mode: \"NX\"})","handlingStrategy":"validation","validationCode":"func validJSONSetMode(mode string) error {\n    switch strings.ToUpper(mode) {\n    case \"\", \"NX\", \"XX\":\n        return nil\n    default:\n        return fmt.Errorf(\"JSON.SET mode must be NX or XX, got %q\", mode)\n    }\n}","typeGuard":"func isValidJSONSetMode(mode string) bool {\n    switch strings.ToUpper(mode) {\n    case \"\", \"NX\", \"XX\":\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Whitelist mode to {\"\", \"NX\", \"XX\"} before calling JSONSetWithArgs/JSONSetMode.","Use JSONSet (no mode argument) when no conditional flag is needed.","Trim whitespace from user-supplied mode strings before validation."],"tags":["json","jsonset","panic","validation","redisjson","mode"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}