Repository: optuna/optuna
Pull request: Made error message for `create_study`'s direction easier to understand `optuna.study`
issue: #5806

## Motivation

Users sometimes makes the mistake of passing the list of directions to the direction argument. The error message for this mistake is hard to understand what is the problem.

- Correct
```python
optuna.create_study(directions=["minimize", "minimize"])
```
- Wrong

Using direction instead of directions

```python
optuna.create_study(direction=["minimize", "minimize"])
```
```
ValueError: Please set either 'minimize' or 'maximize' to direction. You can also set the corresponding `StudyDirection` member.
```


## Description of the changes
The error message displayed when a list object, is assigned to the direction parameter of create_study has been changed as follows.

- previous
```
ValueError: Please set either 'minimize' or 'maximize' to direction. You can also set the corresponding `StudyDirection` member.
```

- new
```
ValueError: For multi-objective optimization, using `directions` instead of `direction`.
```


Problem statement:
Make error message for `create_study`'s `direction` easier to understand
### Motivation

Users sometimes make the mistake of passing the list of directions to the `direction` argument. The error message for this mistake is hard to understand what is the problem.

* Correct

```python
optuna.create_study(directions=["minimize", "minimize"])
```

* Wrong

Using `direction` instead of `directions`

```python
optuna.create_study(direction=["minimize", "minimize"])
```

```
ValueError: Please set either 'minimize' or 'maximize' to direction. You can also set the corresponding `StudyDirection` member.
```

### Suggestion

We can make the error message more helpful for the mistake. It can be something like "for multi-objective optimization, using directions instead of direction".

### Additional context (optional)

_No response_

Hints from issue discussion:
Hello,
I would like to take this issue. Can I know which file I have to change it for the error message. There are many files so it is confusing. 

Thank you.
Thanks! It's `study/study.py`.

https://github.com/optuna/optuna/blob/b29fdff87e46fd1c1e025e23af005c9a9ad80a11/optuna/study/study.py#L1254-L1257

Commit message: add test

Patch to review:
diff --git a/optuna/study/study.py b/optuna/study/study.py
index 8bf625117bb..58b3bdcbd69 100644
--- a/optuna/study/study.py
+++ b/optuna/study/study.py
@@ -1239,6 +1239,10 @@ def objective(trial):
     elif direction is not None and directions is not None:
         raise ValueError("Specify only one of `direction` and `directions`.")
     elif direction is not None:
+        if isinstance(direction, Sequence) and not isinstance(direction, str):
+            raise ValueError(
+                "For multi-objective optimization, using `directions` instead of `direction`."
+            )
         directions = [direction]
     elif directions is not None:
         directions = list(directions)
diff --git a/tests/study_tests/test_study.py b/tests/study_tests/test_study.py
index e22605daa95..2fa6ee13173 100644
--- a/tests/study_tests/test_study.py
+++ b/tests/study_tests/test_study.py
@@ -148,8 +148,19 @@ def test_optimize_with_direction() -> None:
     assert study.direction == StudyDirection.MAXIMIZE
     check_study(study)
 
-    with pytest.raises(ValueError):
+    with pytest.raises(ValueError) as e:
         create_study(direction="test")
+    assert str(e.value) == (
+        "Please set either 'minimize' or 'maximize' to direction. You can also set the "
+        + "corresponding `StudyDirection` member."
+    )
+
+    with pytest.raises(ValueError) as e:
+        create_study(direction=["maximize", "minimize"])
+    assert (
+        str(e.value)
+        == "For multi-objective optimization, using `directions` instead of `direction`."
+    )
 
 
 @pytest.mark.parametrize("n_trials", (0, 1, 20))
@@ -1152,15 +1163,18 @@ def test_create_study_with_multi_objectives() -> None:
     assert study.directions == [StudyDirection.MAXIMIZE, StudyDirection.MINIMIZE]
     assert study._is_multi_objective()
 
-    with pytest.raises(ValueError):
+    with pytest.raises(ValueError) as e:
         # Empty `direction` isn't allowed.
         _ = create_study(directions=[])
+    assert str(e.value) == "The number of objectives must be greater than 0."
 
-    with pytest.raises(ValueError):
+    with pytest.raises(ValueError) as e:
         _ = create_study(direction="minimize", directions=["maximize"])
+    assert str(e.value) == "Specify only one of `direction` and `directions`."
 
-    with pytest.raises(ValueError):
+    with pytest.raises(ValueError) as e:
         _ = create_study(direction="minimize", directions=[])
+    assert str(e.value) == "Specify only one of `direction` and `directions`."
 
 
 def test_create_study_with_direction_object() -> None:


Code review comments:
diff_hunk: @@ -1239,6 +1239,10 @@ def objective(trial):
     elif direction is not None and directions is not None:
         raise ValueError("Specify only one of `direction` and `directions`.")
     elif direction is not None:
+        if isinstance(direction, Sequence) and not isinstance(direction, str):
+            raise ValueError(
+                "For multi-objective optimization, using `directions` instead of `direction`."
path: optuna/study/study.py
text: @user1:
[nit] Imperative form is conventional.
```suggestion
                "Use `directions` instead of `direction` for multi-objective optimization."
```