Repository: django/django

Issue:
# Fixed #36352 -- Improved error message for fields excluded by prior values()/values_list() calls.

#### Trac ticket number
<!-- Replace XXXXX with the corresponding Trac ticket number, or delete the line and write "N/A" if this is a trivial PR. -->

ticket-36352

Added context-aware error messages to distinguish between masked annotations and unpromoted aliases in chained values()/values_list() calls.

#### Checklist
- [x] This PR targets the `main` branch. <!-- Backports will be evaluated and done by mergers, when necessary. -->
- [x] The commit message is written in past tense, mentions the ticket number, and ends with a period.
- [x] I have checked the "Has patch" ticket flag in the Trac system.
- [x] I have added or updated relevant tests.
- [ ] I have added or updated relevant docs, including release notes if applicable.
- [ ] I have attached screenshots in both light and dark modes for any UI changes.


Implementation patch:
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index e3e6100f24f0..4be450167d78 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -2585,10 +2585,17 @@ def set_values(self, fields):
                         annotation_names.append(f)
                         selected[f] = f
                     elif f in self.annotations:
-                        raise FieldError(
-                            f"Cannot select the '{f}' alias. Use annotate() to "
-                            "promote it."
-                        )
+                        if self.annotation_select:
+                            raise FieldError(
+                                f"Cannot select the '{f}' alias. It was excluded "
+                                f"by a previous values() or values_list() call. "
+                                f"Include '{f}' in that call to select it."
+                            )
+                        else:
+                            raise FieldError(
+                                f"Cannot select the '{f}' alias. Use annotate() "
+                                f"to promote it."
+                            )
                     else:
                         # Call `names_to_path` to ensure a FieldError including
                         # annotations about to be masked as valid choices if


Test patch:
diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py
index 6336cabafae9..69a2b4a7c7bc 100644
--- a/tests/annotations/tests.py
+++ b/tests/annotations/tests.py
@@ -482,6 +482,17 @@ def test_values_wrong_annotation(self):
         with self.assertRaisesMessage(FieldError, expected_message % article_fields):
             Book.objects.annotate(annotation=Value(1)).values_list("annotation_typo")
 
+    def test_chained_values_masked_annotation_error_message(self):
+        msg = (
+            "Cannot select the 'author_id' alias. It was excluded by a "
+            "previous values() or values_list() call. Include 'author_id' in "
+            "that call to select it."
+        )
+        with self.assertRaisesMessage(FieldError, msg):
+            Book.objects.annotate(
+                author_name=F("authors__name"), author_id=F("authors__id")
+            ).values("author_name").values("author_id")
+
     def test_decimal_annotation(self):
         salary = Decimal(10) ** -Employee._meta.get_field("salary").decimal_places
         Employee.objects.create(