Throw an exception when creating the execution transition if no transition is available.

Fixes #22996.

PiperOrigin-RevId: 656522163
Change-Id: Ibaf96071f23a3ddd060c6e04aebb73ab33ae05ed
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionTransitionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionTransitionFactory.java
index da02b7a..59770e7 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionTransitionFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionTransitionFactory.java
@@ -19,7 +19,6 @@
 
 import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
-import com.google.common.base.Verify;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -79,7 +78,8 @@
       Caffeine.newBuilder().weakValues().build();
 
   @Override
-  public PatchTransition create(AttributeTransitionData dataWithTargetAttributes) {
+  public PatchTransition create(AttributeTransitionData dataWithTargetAttributes)
+      throws TransitionCreationException {
     // Delete AttributeTransitionData.attributes() so the exec transition doesn't try to read the
     // attributes of the target it's attached to. This is for two reasons:
     //
@@ -93,11 +93,13 @@
             .executionPlatform(dataWithTargetAttributes.executionPlatform())
             .build();
 
+    if (data.analysisData() == null) {
+      throw new TransitionCreationException(
+          "expected a Starlark exec transition definition, but was null");
+    }
     @SuppressWarnings("unchecked")
     TransitionFactory<AttributeTransitionData> starlarkExecTransitionProvider =
-        (TransitionFactory<AttributeTransitionData>)
-            Verify.verifyNotNull(
-                data.analysisData(), "expected a Starlark exec transition definition");
+        (TransitionFactory<AttributeTransitionData>) data.analysisData();
 
     return transitionInstanceCache.get(
         // A Starlark transition keeps the same instance unless we modify its .bzl file.
diff --git a/src/test/java/com/google/devtools/build/lib/rules/platform/PlatformInfoApiTest.java b/src/test/java/com/google/devtools/build/lib/rules/platform/PlatformInfoApiTest.java
index 5d62168..a66372b 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/platform/PlatformInfoApiTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/platform/PlatformInfoApiTest.java
@@ -96,6 +96,26 @@
   }
 
   @Test
+  public void constraints_invalidTarget_error() throws Exception {
+    checkError(
+        "foo",
+        "my_platform",
+        // TODO: https://github.com/bazelbuild/bazel/issues/23126 - Have a better error message.
+        // Something like "Invalid dependency :lib does not provide ConstraintValueInfo"
+        "errors encountered while analyzing target",
+        """
+        cc_library(name = "lib")
+
+        platform(
+            name = "my_platform",
+            constraint_values = [
+                ":lib",
+            ],
+        )
+        """);
+  }
+
+  @Test
   public void constraints_parent() throws Exception {
     constraintBuilder("//foo:setting1").addConstraintValue("value1").write();
     constraintBuilder("//foo:setting2").addConstraintValue("value2").write();