Repository: bazelbuild/bazel
Issue: Unrecoverable error using bzlmod
Labels: type: bug
team-Configurability
untriaged

### Description of the bug:


While making rules_dotnet bzlmod compatible I encountered an Bazel crash:
```
FATAL: bazel crashed due to an internal error. Printing stack trace:
java.lang.RuntimeException: Unrecoverable error while evaluating node 'ConfiguredTargetKey{label=//dotnet/private/tests/warning_settings:csharp_treat_warnings_as_errors_config_test, config=BuildConfigurationKey[0cfe0dbd956d9b571c331623c346c60b3b866c9f5bcd256de36fa22c2b46c2b8]}' (requested by nodes )
	at com.google.devtools.build.skyframe.AbstractParallelEvaluator$Evaluate.run(AbstractParallelEvaluator.java:633)
	at com.google.devtools.build.lib.concurrent.AbstractQueueVisitor$WrappedRunnable.run(AbstractQueueVisitor.java:365)
	at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinPool.scan(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: com.google.devtools.build.lib.cmdline.LabelSyntaxException: invalid repository name '@[unknown repo '' requested from @bazel_skylib~1.4.2]': repo names may contain only A-Z, a-z, 0-9, '-', '_', '.' and '~' and must not start with '~'
	at com.google.devtools.build.lib.cmdline.Label.parseAbsoluteUnchecked(Label.java:240)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(Unknown Source)
	at java.base/java.util.HashMap$KeySpliterator.forEachRemaining(Unknown Source)
	at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
	at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
	at java.base/java.util.stream.ReferencePipeline.collect(Unknown Source)
	at com.google.devtools.build.lib.analysis.starlark.StarlarkTransition.getRelevantStarlarkSettingsFromTransition(StarlarkTransition.java:393)
	at com.google.devtools.build.lib.analysis.starlark.StarlarkTransition.lambda$getAllStarlarkBuildSettings$0(StarlarkTransition.java:123)
	at com.google.devtools.build.lib.analysis.starlark.StarlarkTransition$StarlarkTransitionVisitor.accept(StarlarkTransition.java:430)
	at com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition.visit(ConfigurationTransition.java:101)
	at com.google.devtools.build.lib.analysis.config.transitions.ComposingTransition.visit(ComposingTransition.java:99)
	at com.google.devtools.build.lib.analysis.config.transitions.ComposingTransition.visit(ComposingTransition.java:99)
	at com.google.devtools.build.lib.analysis.starlark.StarlarkTransition.getAllStarlarkBuildSettings(StarlarkTransition.java:119)
	at com.google.devtools.build.lib.analysis.config.ConfigurationResolver.getStarlarkBuildSettingsDetailsValue(ConfigurationResolver.java:407)
	at com.google.devtools.build.lib.analysis.config.ConfigurationResolver.applyTransitionWithSkyframe(ConfigurationResolver.java:388)
	at com.google.devtools.build.lib.analysis.config.ConfigurationResolver.resolveGenericTransition(ConfigurationResolver.java:233)
	at com.google.devtools.build.lib.analysis.config.ConfigurationResolver.resolveConfiguration(ConfigurationResolver.java:192)
	at com.google.devtools.build.lib.analysis.config.ConfigurationResolver.resolveConfigurations(ConfigurationResolver.java:151)
	at com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.computeDependencies(ConfiguredTargetFunction.java:869)
	at com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.compute(ConfiguredTargetFunction.java:371)
	at com.google.devtools.build.skyframe.AbstractParallelEvaluator$Evaluate.run(AbstractParallelEvaluator.java:562)
	... 7 more
Caused by: com.google.devtools.build.lib.cmdline.LabelSyntaxException: invalid repository name '@[unknown repo '' requested from @bazel_skylib~1.4.2]': repo names may contain only A-Z, a-z, 0-9, '-', '_', '.' and '~' and must not start with '~'
	at com.google.devtools.build.lib.cmdline.LabelParser.syntaxErrorf(LabelParser.java:208)
	at com.google.devtools.build.lib.cmdline.RepositoryName.validate(RepositoryName.java:160)
	at com.google.devtools.build.lib.cmdline.LabelParser$Parts.validateRepoName(LabelParser.java:180)
	at com.google.devtools.build.lib.cmdline.LabelParser$Parts.validateAndCreate(LabelParser.java:72)
	at com.google.devtools.build.lib.cmdline.LabelParser$Parts.parse(LabelParser.java:164)
	at com.google.devtools.build.lib.cmdline.Label.parseCanonical(Label.java:123)
	at com.google.devtools.build.lib.cmdline.Label.parseAbsoluteUnchecked(Label.java:238)
	... 30 more
```

Reproduction is available at https://github.com/bazelbuild/rules_dotnet/pull/387 by running `bazel test //... --enable_bzlmod`

cc @fmeum

### Which category does this issue belong to?


_No response_

### What's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.


_No response_

### Which operating system are you running Bazel on?


Linux Fedora 38

### What is the output of `bazel info release`?


release 6.3.2

### If `bazel info release` returns `development version` or `(@non-git)`, tell us how you built Bazel.


_No response_

### What's the output of `git remote get-url origin; git rev-parse master; git rev-parse HEAD` ?


_No response_

### Is this a regression? If yes, please try to identify the Bazel commit where the bug was introduced.


_No response_

### Have you found anything relevant by searching the web?

_No response_

### Any other information, logs, or outputs that you want to share?

_No response_

Issue comments:
A fix for this issue has been included in [Bazel 6.4.0 RC2](https://releases.bazel.build/6.4.0/rc2/index.html). Please test out the release candidate and report any issues as soon as possible. Thanks!

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
index 19bb09104c6938..861504ed602906 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
@@ -21,6 +21,7 @@
 import com.google.devtools.build.lib.analysis.config.StarlarkDefinedConfigTransition.Settings;
 import com.google.devtools.build.lib.cmdline.BazelModuleContext;
 import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
 import com.google.devtools.build.lib.starlarkbuildapi.config.ConfigGlobalLibraryApi;
 import com.google.devtools.build.lib.starlarkbuildapi.config.ConfigurationTransitionApi;
 import java.util.HashSet;
@@ -53,10 +54,10 @@ public ConfigurationTransitionApi transition(
     StarlarkSemantics semantics = thread.getSemantics();
     List<String> inputsList = Sequence.cast(inputs, String.class, "inputs");
     List<String> outputsList = Sequence.cast(outputs, String.class, "outputs");
-    validateBuildSettingKeys(inputsList, Settings.INPUTS);
-    validateBuildSettingKeys(outputsList, Settings.OUTPUTS);
     BazelModuleContext moduleContext =
         BazelModuleContext.of(Module.ofInnermostEnclosingStarlarkFunction(thread));
+    validateBuildSettingKeys(inputsList, Settings.INPUTS, moduleContext.packageContext());
+    validateBuildSettingKeys(outputsList, Settings.OUTPUTS, moduleContext.packageContext());
     Location location = thread.getCallerLocation();
     return StarlarkDefinedConfigTransition.newRegularTransition(
         implementation,
@@ -76,15 +77,17 @@ public ConfigurationTransitionApi analysisTestTransition(
       throws EvalException {
     Map<String, Object> changedSettingsMap =
         Dict.cast(changedSettings, String.class, Object.class, "changed_settings dict");
-    validateBuildSettingKeys(changedSettingsMap.keySet(), Settings.OUTPUTS);
     BazelModuleContext moduleContext =
         BazelModuleContext.of(Module.ofInnermostEnclosingStarlarkFunction(thread));
+    validateBuildSettingKeys(
+        changedSettingsMap.keySet(), Settings.OUTPUTS, moduleContext.packageContext());
     Location location = thread.getCallerLocation();
     return StarlarkDefinedConfigTransition.newAnalysisTestTransition(
         changedSettingsMap, moduleContext.repoMapping(), moduleContext.label(), location);
   }
 
-  private void validateBuildSettingKeys(Iterable<String> optionKeys, Settings keyErrorDescriptor)
+  private void validateBuildSettingKeys(
+      Iterable<String> optionKeys, Settings keyErrorDescriptor, Label.PackageContext packageContext)
       throws EvalException {
 
     HashSet<String> processedOptions = Sets.newHashSet();
@@ -93,8 +96,16 @@ private void validateBuildSettingKeys(Iterable<String> optionKeys, Settings keyE
     for (String optionKey : optionKeys) {
       if (!optionKey.startsWith(COMMAND_LINE_OPTION_PREFIX)) {
         try {
-          Label.parseAbsoluteUnchecked(optionKey);
-        } catch (IllegalArgumentException e) {
+          Label label = Label.parseWithRepoContext(optionKey, packageContext);
+          if (!label.getRepository().isVisible()) {
+            throw Starlark.errorf(
+                "invalid transition %s '%s': no repo visible as @%s from %s",
+                singularErrorDescriptor,
+                label,
+                label.getRepository().getName(),
+                label.getRepository().getOwnerRepoDisplayString());
+          }
+        } catch (LabelSyntaxException e) {
           throw Starlark.errorf(
               "invalid transition %s '%s'. If this is intended as a native option, "
                   + "it must begin with //command_line_option: %s",


Test patch:
diff --git a/src/test/java/com/google/devtools/build/lib/rules/LabelBuildSettingTest.java b/src/test/java/com/google/devtools/build/lib/rules/LabelBuildSettingTest.java
index 24fcfd5962afa1..2b1caf109e6cca 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/LabelBuildSettingTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/LabelBuildSettingTest.java
@@ -339,4 +339,48 @@ public void transitionOutput_otherRepo() throws Exception {
     assertThat(getConfiguredTarget("//test:buildme")).isNotNull();
     assertNoEvents();
   }
+
+  @Test
+  public void testInvisibleRepoInLabelResultsInEarlyError() throws Exception {
+    setBuildLanguageOptions("--enable_bzlmod");
+
+    scratch.file("MODULE.bazel");
+    scratch.file(
+        "test/defs.bzl",
+        "def _setting_impl(ctx):",
+        "  return []",
+        "string_flag = rule(",
+        "  implementation = _setting_impl,",
+        "  build_setting = config.string(flag=True),",
+        ")",
+        "def _transition_impl(settings, attr):",
+        "  return {'//test:formation': 'mesa'}",
+        "formation_transition = transition(",
+        "  implementation = _transition_impl,",
+        "  inputs = ['@foobar//test:formation'],", // invalid repo name
+        "  outputs = ['//test:formation'],",
+        ")",
+        "def _impl(ctx):",
+        "  return []",
+        "state = rule(",
+        "  implementation = _impl,",
+        "  cfg = formation_transition,",
+        "  attrs = {",
+        "    '_allowlist_function_transition': attr.label(",
+        "        default = '//tools/allowlists/function_transition_allowlist',",
+        "    ),",
+        "  })");
+    scratch.file(
+        "test/BUILD",
+        "load('//test:defs.bzl', 'state', 'string_flag')",
+        "state(name = 'arizona')",
+        "string_flag(name = 'formation', build_setting_default = 'canyon')");
+
+    reporter.removeHandler(failFastHandler);
+    getConfiguredTarget("//test:arizona");
+
+    assertContainsEvent(
+        "Error in transition: invalid transition input '@[unknown repo 'foobar' requested from @]"
+            + "//test:formation': no repo visible as @foobar from main repository");
+  }
 }