go-redis/redis · error

redis: JSON.SET mode must be NX or XX

Error message

redis: JSON.SET mode must be NX or XX

What it means

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.

Source

Thrown at json.go:648

func (c cmdable) JSONSetWithArgs(ctx context.Context, key, path string, value interface{}, options *JSONSetArgsOptions) *StatusCmd {
	var bytes []byte
	var err error
	switch v := value.(type) {
	case string:
		bytes = []byte(v)
	case []byte:
		bytes = v
	default:
		bytes, err = json.Marshal(v)
	}
	args := []interface{}{"JSON.SET", key, path, util.BytesToString(bytes)}
	if options != nil {
		if options.Mode != "" {
			switch strings.ToUpper(options.Mode) {
			case "XX", "NX":
				args = append(args, strings.ToUpper(options.Mode))
			default:
				panic("redis: JSON.SET mode must be NX or XX")
			}
		}
		if options.FPHA != "" {
			args = append(args, "FPHA", string(options.FPHA))
		}
	}
	cmd := NewStatusCmd(ctx, args...)
	if err != nil {
		cmd.SetErr(err)
	} else {
		_ = c(ctx, cmd)
	}
	return cmd
}

// JSONStrAppend appends the JSON-string values to the string at the specified path.
// For more information, see https://redis.io/commands/json.strappend
func (c cmdable) JSONStrAppend(ctx context.Context, key, path, value string) *IntPointerSliceCmd {

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Pass only "NX" or "XX" (any case) as the mode, or empty string to omit the flag.
  2. Validate user-supplied mode against {"", "NX", "XX"} before calling JSONSetWithArgs.
  3. Use JSONSet (no mode) when no conditional flag is needed.

Example fix

// before
client.JSONSetWithArgs(ctx, key, "$", v, &redis.JSONSetArgsOptions{Mode: "EX"})

// after
client.JSONSetWithArgs(ctx, key, "$", v, &redis.JSONSetArgsOptions{Mode: "NX"})
Defensive patterns

Strategy: validation

Validate before calling

func validJSONSetMode(mode string) error {
    switch strings.ToUpper(mode) {
    case "", "NX", "XX":
        return nil
    default:
        return fmt.Errorf("JSON.SET mode must be NX or XX, got %q", mode)
    }
}

Type guard

func isValidJSONSetMode(mode string) bool {
    switch strings.ToUpper(mode) {
    case "", "NX", "XX":
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Calling JSONSetMode/JSONSetWithArgs with mode = "SET", "EX", "XXNX", or any string that is not NX/XX.

Common situations: 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.

Related errors


AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06). Data as JSON: /data/errors/683f5ba50aacbf99.json. Report an issue: GitHub.