starlark: remove EvalException(Location) -- easy cases

This change removes the Location argument to new EvalException() if:
- location is null or BUILTIN;
- location is rule.getLocation(), if the code is only reached while
  doing rule analysis, as analysis failures always report the rule
  location.
- the exception is never thrown out of a Starlark call; that is,
  it is only used locally in Java code.

Trickier cases are left for a follow-up.

Also, use Starlark.errorf to construct error messages.

PiperOrigin-RevId: 325546962
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/StarlarkProviderValidationUtil.java b/src/main/java/com/google/devtools/build/lib/analysis/StarlarkProviderValidationUtil.java
index 046a3c9..e18cd98 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/StarlarkProviderValidationUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/StarlarkProviderValidationUtil.java
@@ -18,6 +18,7 @@
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Starlark;
 
 /** Utility class to validate results of executing Starlark rules and aspects. */
 public class StarlarkProviderValidationUtil {
@@ -25,17 +26,17 @@
     ImmutableSet<Artifact> treeArtifactsConflictingWithFiles =
         ruleContext.getAnalysisEnvironment().getTreeArtifactsConflictingWithFiles();
     if (!treeArtifactsConflictingWithFiles.isEmpty()) {
-      throw new EvalException(
-          "The following directories were also declared as files:\n"
-              + artifactsDescription(treeArtifactsConflictingWithFiles));
+      throw Starlark.errorf(
+          "The following directories were also declared as files:\n%s",
+          artifactsDescription(treeArtifactsConflictingWithFiles));
     }
 
     ImmutableSet<Artifact> orphanArtifacts =
         ruleContext.getAnalysisEnvironment().getOrphanArtifacts();
     if (!orphanArtifacts.isEmpty()) {
-      throw new EvalException(
-          "The following files have no generating action:\n"
-              + artifactsDescription(orphanArtifacts));
+      throw Starlark.errorf(
+          "The following files have no generating action:\n%s",
+          artifactsDescription(orphanArtifacts));
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java
index d369363..b20f8e4 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java
@@ -73,7 +73,6 @@
 import com.google.devtools.build.lib.server.FailureDetails.Spawn.Code;
 import com.google.devtools.build.lib.starlarkbuildapi.CommandLineArgsApi;
 import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.Location;
 import com.google.devtools.build.lib.syntax.Sequence;
 import com.google.devtools.build.lib.syntax.StarlarkList;
 import com.google.devtools.build.lib.util.DetailedExitCode;
@@ -262,8 +261,8 @@
   public Sequence<String> getStarlarkArgv() throws EvalException {
     try {
       return StarlarkList.immutableCopyOf(getArguments());
-    } catch (CommandLineExpansionException exception) {
-      throw new EvalException(Location.BUILTIN, exception);
+    } catch (CommandLineExpansionException ex) {
+      throw new EvalException(ex);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/Args.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/Args.java
index 2aa929a..3a8c165 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/Args.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/Args.java
@@ -466,11 +466,9 @@
         throws EvalException {
       Starlark.checkMutable(this);
       if (!SingleStringArgFormatter.isValid(paramFileArg)) {
-        throw new EvalException(
-            String.format(
-                "Invalid value for parameter \"param_file_arg\": "
-                    + "Expected string with a single \"%s\"",
-                paramFileArg));
+        throw Starlark.errorf(
+            "Invalid value for parameter \"param_file_arg\": Expected string with a single \"%s\"",
+            paramFileArg);
       }
       this.flagFormatString = paramFileArg;
       this.alwaysUseParamFile = useAlways;
@@ -489,7 +487,7 @@
           parameterFileType = ParameterFileType.UNQUOTED;
           break;
         default:
-          throw new EvalException(
+          throw Starlark.errorf(
               "Invalid value for parameter \"format\": Expected one of \"shell\", \"multiline\"");
       }
       this.parameterFileType = parameterFileType;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java
index 6c6d2fb..3e795c4 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java
@@ -102,8 +102,7 @@
   private static void checkForBlacklistedOptions(StarlarkDefinedConfigTransition transition)
       throws EvalException {
     if (transition.getOutputs().contains("//command_line_option:define")) {
-      throw new EvalException(
-          transition.getLocationForErrorReporting(),
+      throw Starlark.errorf(
           "Starlark transition on --define not supported - try using build settings"
               + " (https://docs.bazel.build/skylark/config.html#user-defined-build-settings).");
     }
@@ -123,18 +122,14 @@
           Sets.newLinkedHashSet(starlarkTransition.getOutputs());
       for (String outputKey : transition.keySet()) {
         if (!remainingOutputs.remove(outputKey)) {
-          throw new EvalException(
-              starlarkTransition.getLocationForErrorReporting(),
-              String.format("transition function returned undeclared output '%s'", outputKey));
+          throw Starlark.errorf("transition function returned undeclared output '%s'", outputKey);
         }
       }
 
       if (!remainingOutputs.isEmpty()) {
-        throw new EvalException(
-            starlarkTransition.getLocationForErrorReporting(),
-            String.format(
-                "transition outputs [%s] were not defined by transition function",
-                Joiner.on(", ").join(remainingOutputs)));
+        throw Starlark.errorf(
+            "transition outputs [%s] were not defined by transition function",
+            Joiner.on(", ").join(remainingOutputs));
       }
     }
   }
@@ -213,11 +208,9 @@
       }
 
       if (!remainingInputs.isEmpty()) {
-        throw new EvalException(
-            starlarkTransition.getLocationForErrorReporting(),
-            String.format(
-                "transition inputs [%s] do not correspond to valid settings",
-                Joiner.on(", ").join(remainingInputs)));
+        throw Starlark.errorf(
+            "transition inputs [%s] do not correspond to valid settings",
+            Joiner.on(", ").join(remainingInputs));
       }
 
       return dict;
@@ -266,11 +259,8 @@
         }
         try {
           if (!optionInfoMap.containsKey(optionName)) {
-            throw new EvalException(
-                starlarkTransition.getLocationForErrorReporting(),
-                String.format(
-                    "transition output '%s' does not correspond to a valid setting",
-                    entry.getKey()));
+            throw Starlark.errorf(
+                "transition output '%s' does not correspond to a valid setting", entry.getKey());
           }
 
           OptionInfo optionInfo = optionInfoMap.get(optionName);
@@ -306,23 +296,19 @@
           } else if (optionValue instanceof String) {
             convertedValue = def.getConverter().convert((String) optionValue);
           } else {
-            throw new EvalException(
-                starlarkTransition.getLocationForErrorReporting(),
-                "Invalid value type for option '" + optionName + "'");
+            throw Starlark.errorf("Invalid value type for option '%s'", optionName);
           }
           field.set(options, convertedValue);
           convertedNewValues.put(entry.getKey(), convertedValue);
         } catch (IllegalArgumentException e) {
-          throw new EvalException(
-              starlarkTransition.getLocationForErrorReporting(),
-              "IllegalArgumentError for option '" + optionName + "': " + e.getMessage());
+          throw Starlark.errorf(
+              "IllegalArgumentError for option '%s': %s", optionName, e.getMessage());
         } catch (IllegalAccessException e) {
           throw new RuntimeException(
               "IllegalAccess for option " + optionName + ": " + e.getMessage());
         } catch (OptionsParsingException e) {
-          throw new EvalException(
-              starlarkTransition.getLocationForErrorReporting(),
-              "OptionsParsingError for option '" + optionName + "': " + e.getMessage());
+          throw Starlark.errorf(
+              "OptionsParsingError for option '%s': %s", optionName, e.getMessage());
         }
       }
     }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkActionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkActionFactory.java
index 9264d1e..0297222 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkActionFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkActionFactory.java
@@ -452,9 +452,9 @@
       List<String> command = Sequence.cast(commandList, String.class, "command");
       builder.setShellCommand(command);
     } else {
-      throw new EvalException(
-          "expected string or list of strings for command instead of "
-              + Starlark.type(commandUnchecked));
+      throw Starlark.errorf(
+          "expected string or list of strings for command instead of %s",
+          Starlark.type(commandUnchecked));
     }
     if (argumentList.size() > 0) {
       // When we use a shell command, add an empty argument before other arguments.
@@ -493,9 +493,9 @@
         ParamFileInfo paramFileInfo = args.getParamFileInfo();
         builder.addCommandLine(args.build(), paramFileInfo);
       } else {
-        throw new EvalException(
-            "expected list of strings or ctx.actions.args() for arguments instead of "
-                + Starlark.type(value));
+        throw Starlark.errorf(
+            "expected list of strings or ctx.actions.args() for arguments instead of %s",
+            Starlark.type(value));
       }
     }
     if (!stringArgs.isEmpty()) {
@@ -566,11 +566,10 @@
         } else if (toolUnchecked instanceof FilesToRunProvider) {
           builder.addTool((FilesToRunProvider) toolUnchecked);
         } else {
-          throw new EvalException(
-              "expected value of type 'File or FilesToRunProvider' for "
-                  + "a member of parameter 'tools' but got "
-                  + Starlark.type(toolUnchecked)
-                  + " instead");
+          throw Starlark.errorf(
+              "expected value of type 'File or FilesToRunProvider' for a member of parameter"
+                  + " 'tools' but got %s instead",
+              Starlark.type(toolUnchecked));
         }
       }
     } else {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java
index 0a22b53..4adf858 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java
@@ -85,7 +85,7 @@
           ImmutableList.copyOf(Sequence.cast(fileTypesObj, String.class, "allow_files argument"));
       builder.allowedFileTypes(FileType.of(arg));
     } else {
-      throw new EvalException(attr + " should be a boolean or a string list");
+      throw Starlark.errorf("%s should be a boolean or a string list", attr);
     }
   }
 
@@ -163,7 +163,7 @@
     if (containsNonNoneKey(arguments, EXECUTABLE_ARG) && (Boolean) arguments.get(EXECUTABLE_ARG)) {
       builder.setPropertyFlag("EXECUTABLE");
       if (!containsNonNoneKey(arguments, CONFIGURATION_ARG)) {
-        throw new EvalException(
+        throw Starlark.errorf(
             "cfg parameter is mandatory when executable=True is provided. Please see "
                 + "https://www.bazel.build/versions/master/docs/skylark/rules.html#configurations "
                 + "for more details.");
@@ -172,7 +172,7 @@
 
     if (containsNonNoneKey(arguments, ALLOW_FILES_ARG)
         && containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
-      throw new EvalException("Cannot specify both allow_files and allow_single_file");
+      throw Starlark.errorf("Cannot specify both allow_files and allow_single_file");
     }
 
     if (containsNonNoneKey(arguments, ALLOW_FILES_ARG)) {
@@ -219,7 +219,7 @@
               || trans instanceof TransitionFactory
               || trans instanceof StarlarkDefinedConfigTransition;
       if (isSplit && defaultValue instanceof StarlarkLateBoundDefault) {
-        throw new EvalException(
+        throw Starlark.errorf(
             "late-bound attributes must not have a split configuration transition");
       }
       if (trans.equals("host")) {
@@ -239,7 +239,7 @@
           builder.hasAnalysisTestTransition();
         } else {
           if (!thread.getSemantics().experimentalStarlarkConfigTransitions()) {
-            throw new EvalException(
+            throw Starlark.errorf(
                 "Starlark-defined transitions on rule attributes is experimental and disabled by "
                     + "default. This API is in development and subject to change at any time. Use "
                     + "--experimental_starlark_config_transitions to use this experimental API.");
@@ -249,7 +249,7 @@
         builder.cfg(new StarlarkAttributeTransitionProvider(starlarkDefinedTransition));
       } else if (!trans.equals("target")) {
         // TODO(b/121134880): update error message when starlark build configurations is ready.
-        throw new EvalException("cfg must be either 'host' or 'target'.");
+        throw Starlark.errorf("cfg must be either 'host' or 'target'.");
       }
     }
 
@@ -311,7 +311,7 @@
       } else if (obj instanceof Provider) {
         Provider constructor = (Provider) obj;
         if (!constructor.isExported()) {
-          throw new EvalException(
+          throw Starlark.errorf(
               "Providers should be top-level values in extension files that define them.");
         }
         result.add(StarlarkProviderIdentifier.forKey(constructor.getKey()));
@@ -330,14 +330,12 @@
 
     for (Object o : starlarkList) {
       if (!(o instanceof Sequence)) {
-        throw new EvalException(
-            String.format(errorMsg, PROVIDERS_ARG, "an element of type " + Starlark.type(o)));
+        throw Starlark.errorf(errorMsg, PROVIDERS_ARG, "an element of type " + Starlark.type(o));
       }
       for (Object value : (Sequence) o) {
         if (!isProvider(value)) {
-          throw new EvalException(
-              String.format(
-                  errorMsg, argumentName, "list with an element of type " + Starlark.type(value)));
+          throw Starlark.errorf(
+              errorMsg, argumentName, "list with an element of type " + Starlark.type(value));
         }
       }
       providersList.add(getStarlarkProviderIdentifiers((Sequence<?>) o));
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkErrorReporter.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkErrorReporter.java
index 80d70a3..96b5fca 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkErrorReporter.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkErrorReporter.java
@@ -16,6 +16,7 @@
 import com.google.devtools.build.lib.analysis.RuleErrorConsumer;
 import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Starlark;
 
 /**
  * {@link RuleErrorConsumer} for Native implementations of Starlark APIs.
@@ -43,7 +44,7 @@
     try {
       assertNoErrors();
     } catch (RuleErrorException e) {
-      throw new EvalException("error occurred while evaluating builtin function", e);
+      throw Starlark.errorf("error occurred while evaluating builtin function: %s", e.getMessage());
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
index 14159985..00101b8 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
@@ -323,7 +323,7 @@
             new StarlarkCallbackHelper(
                 (StarlarkFunction) implicitOutputs, thread.getSemantics(), bazelContext);
         builder.setImplicitOutputsFunction(
-            new StarlarkImplicitOutputsFunctionWithCallback(callback, thread.getCallerLocation()));
+            new StarlarkImplicitOutputsFunctionWithCallback(callback));
       } else {
         builder.setImplicitOutputsFunction(
             new StarlarkImplicitOutputsFunctionWithMap(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleContext.java
index cca3bfc..cd59772 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleContext.java
@@ -295,7 +295,7 @@
           "Cannot add outputs to immutable Outputs object");
       if (outputs.containsKey(key)
           || (context.isExecutable() && EXECUTABLE_OUTPUT_NAME.equals(key))) {
-        throw new EvalException("Multiple outputs with the same key: " + key);
+        throw Starlark.errorf("Multiple outputs with the same key: %s", key);
       }
       outputs.put(key, value);
     }
@@ -365,11 +365,9 @@
 
     private void checkMutable() throws EvalException {
       if (isImmutable()) {
-        throw new EvalException(
-            String.format(
-                "cannot access outputs of rule '%s' outside of its own "
-                    + "rule implementation function",
-                context.ruleLabelCanonicalName));
+        throw Starlark.errorf(
+            "cannot access outputs of rule '%s' outside of its own rule implementation function",
+            context.ruleLabelCanonicalName);
       }
     }
 
@@ -405,11 +403,10 @@
 
   public void checkMutable(String attrName) throws EvalException {
     if (isImmutable()) {
-      throw new EvalException(
-          String.format(
-              "cannot access field or method '%s' of rule context for '%s' outside of its own rule "
-                  + "implementation function",
-              attrName, ruleLabelCanonicalName));
+      throw Starlark.errorf(
+          "cannot access field or method '%s' of rule context for '%s' outside of its own rule "
+              + "implementation function",
+          attrName, ruleLabelCanonicalName);
     }
   }
 
@@ -593,10 +590,9 @@
   @Nullable
   public Object getBuildSettingValue() throws EvalException {
     if (ruleContext.getRule().getRuleClassObject().getBuildSetting() == null) {
-      throw new EvalException(
-          String.format(
-              "attempting to access 'build_setting_value' of non-build setting %s",
-              ruleLabelCanonicalName));
+      throw Starlark.errorf(
+          "attempting to access 'build_setting_value' of non-build setting %s",
+          ruleLabelCanonicalName);
     }
     ImmutableMap<Label, Object> starlarkFlagSettings =
         ruleContext.getConfiguration().getOptions().getStarlarkOptions();
@@ -719,7 +715,7 @@
     try {
       ShellUtils.tokenize(options, optionString);
     } catch (TokenizationException e) {
-      throw new EvalException(e.getMessage() + " while tokenizing '" + optionString + "'");
+      throw Starlark.errorf("%s while tokenizing '%s'", e.getMessage(), optionString);
     }
     return StarlarkList.immutableCopyOf(options);
   }
@@ -738,7 +734,7 @@
       }
       return LabelExpander.expand(expression, labelMap, labelResolver);
     } catch (NotUniqueExpansionException e) {
-      throw new EvalException(e.getMessage() + " while expanding '" + expression + "'");
+      throw Starlark.errorf("%s while expanding '%s'", e.getMessage(), expression);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/DecompressorValue.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/DecompressorValue.java
index b1a39d4..f0f71e3 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/DecompressorValue.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/DecompressorValue.java
@@ -16,7 +16,7 @@
 
 import com.google.common.base.Optional;
 import com.google.devtools.build.lib.rules.repository.RepositoryFunction.RepositoryFunctionException;
-import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Starlark;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
@@ -110,11 +110,10 @@
       return TarBz2Function.INSTANCE;
     } else {
       throw new RepositoryFunctionException(
-          new EvalException(
-              String.format(
-                  "Expected a file with a .zip, .jar, .war, .tar, .tar.gz, .tgz, .tar.xz, .txz, or "
-                      + ".tar.bz2 suffix (got %s)",
-                  archivePath)),
+          Starlark.errorf(
+              "Expected a file with a .zip, .jar, .war, .tar, .tar.gz, .tgz, .tar.xz, .txz, or "
+                  + ".tar.bz2 suffix (got %s)",
+              archivePath),
           Transience.PERSISTENT);
     }
   }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java
index 02fd447..5db671e 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java
@@ -479,12 +479,11 @@
       Object arg = arguments.get(i);
       if (isRemotable) {
         if (!(arg instanceof String || arg instanceof Label)) {
-          throw new EvalException("Argument " + i + " of execute is neither a label nor a string.");
+          throw Starlark.errorf("Argument %d of execute is neither a label nor a string.", i);
         }
       } else {
         if (!(arg instanceof String || arg instanceof Label || arg instanceof StarlarkPath)) {
-          throw new EvalException(
-              "Argument " + i + " of execute is neither a path, label, nor string.");
+          throw Starlark.errorf("Argument %d of execute is neither a path, label, nor string.", i);
         }
       }
     }
@@ -992,11 +991,10 @@
 
     for (Object o : urlList) {
       if (!(o instanceof String)) {
-        throw new EvalException(
-            String.format(
-                "Expected a string or sequence of strings for 'url' argument, "
-                    + "but got '%s' item in the sequence",
-                Starlark.type(o)));
+        throw Starlark.errorf(
+            "Expected a string or sequence of strings for 'url' argument, but got '%s' item in the"
+                + " sequence",
+            Starlark.type(o));
       }
       result.add((String) o);
     }
@@ -1148,10 +1146,10 @@
         if (authMap.containsKey("type")) {
           if ("basic".equals(authMap.get("type"))) {
             if (!authMap.containsKey("login") || !authMap.containsKey("password")) {
-              throw new EvalException(
-                  "Found request to do basic auth for "
-                      + entry.getKey()
-                      + " without 'login' and 'password' being provided.");
+              throw Starlark.errorf(
+                  "Found request to do basic auth for %s without 'login' and 'password' being"
+                      + " provided.",
+                  entry.getKey());
             }
             String credentials = authMap.get("login") + ":" + authMap.get("password");
             headers.put(
@@ -1163,10 +1161,9 @@
                             .encodeToString(credentials.getBytes(StandardCharsets.UTF_8))));
           } else if ("pattern".equals(authMap.get("type"))) {
             if (!authMap.containsKey("pattern")) {
-              throw new EvalException(
-                  "Found request to do pattern auth for "
-                      + entry.getKey()
-                      + " without a pattern being provided");
+              throw Starlark.errorf(
+                  "Found request to do pattern auth for %s without a pattern being provided",
+                  entry.getKey());
             }
 
             String result = (String) authMap.get("pattern");
@@ -1176,10 +1173,9 @@
 
               if (result.contains(demarcatedComponent)) {
                 if (!authMap.containsKey(component)) {
-                  throw new EvalException(
-                      "Auth pattern contains "
-                          + demarcatedComponent
-                          + " but it was not provided in auth dict.");
+                  throw Starlark.errorf(
+                      "Auth pattern contains %s but it was not provided in auth dict.",
+                      demarcatedComponent);
                 }
               } else {
                 // component isn't in the pattern, ignore it
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AttributeValueSource.java b/src/main/java/com/google/devtools/build/lib/packages/AttributeValueSource.java
index 799c5d6..7effc45 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AttributeValueSource.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AttributeValueSource.java
@@ -14,6 +14,7 @@
 package com.google.devtools.build.lib.packages;
 
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Starlark;
 
 /**
  * An enum that represents different types of rule attributes, based on where their values come
@@ -48,11 +49,10 @@
     }
 
     if (mustHaveStarlarkPrefix && !attrStarlarkName.startsWith(STARLARK_PREFIX)) {
-      throw new EvalException(
-          String.format(
-              "When an attribute value is a function, the attribute must be private "
-                  + "(i.e. start with '%s'). Found '%s'",
-              STARLARK_PREFIX, attrStarlarkName));
+      throw Starlark.errorf(
+          "When an attribute value is a function, the attribute must be private "
+              + "(i.e. start with '%s'). Found '%s'",
+          STARLARK_PREFIX, attrStarlarkName);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/packages/BazelStarlarkContext.java b/src/main/java/com/google/devtools/build/lib/packages/BazelStarlarkContext.java
index d0babac..24a7b3b 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/BazelStarlarkContext.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/BazelStarlarkContext.java
@@ -20,6 +20,7 @@
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Starlark;
 import com.google.devtools.build.lib.syntax.StarlarkThread;
 import javax.annotation.Nullable;
 
@@ -132,7 +133,7 @@
    */
   public void checkLoadingOrWorkspacePhase(String function) throws EvalException {
     if (phase == Phase.ANALYSIS) {
-      throw new EvalException("'" + function + "' cannot be called during the analysis phase");
+      throw Starlark.errorf("'%s' cannot be called during the analysis phase", function);
     }
   }
 
@@ -143,7 +144,7 @@
    */
   public void checkLoadingPhase(String function) throws EvalException {
     if (phase != Phase.LOADING) {
-      throw new EvalException("'" + function + "' can only be called during the loading phase");
+      throw Starlark.errorf("'%s' can only be called during the loading phase", function);
     }
   }
 
@@ -154,7 +155,7 @@
    */
   public void checkWorkspacePhase(String function) throws EvalException {
     if (phase != Phase.WORKSPACE) {
-      throw new EvalException("'" + function + "' can only be called during workspace loading");
+      throw Starlark.errorf("'%s' can only be called during workspace loading", function);
     }
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ConstantRuleVisibility.java b/src/main/java/com/google/devtools/build/lib/packages/ConstantRuleVisibility.java
index 6c324a5..935d48d 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ConstantRuleVisibility.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ConstantRuleVisibility.java
@@ -21,6 +21,7 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Starlark;
 import java.io.Serializable;
 import java.util.Collections;
 import java.util.List;
@@ -86,7 +87,7 @@
     for (Label label : labels) {
       visibility = tryParse(label);
       if (visibility != null) {
-        throw new EvalException(
+        throw Starlark.errorf(
             "Public or private visibility labels (e.g. //visibility:public or"
                 + " //visibility:private) cannot be used in combination with other labels");
       }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/DefaultPackageArguments.java b/src/main/java/com/google/devtools/build/lib/packages/DefaultPackageArguments.java
index e8c1b6d..ffca6d7 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/DefaultPackageArguments.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/DefaultPackageArguments.java
@@ -49,12 +49,8 @@
     @Override
     protected void process(Package.Builder pkgBuilder, Location location,
         List<Label> value) throws EvalException {
-      try {
-        pkgBuilder.setDefaultVisibility(
-            PackageUtils.getVisibility(pkgBuilder.getBuildFileLabel(), value));
-      } catch (EvalException e) {
-        throw new EvalException(location, e.getMessage());
-      }
+      pkgBuilder.setDefaultVisibility(
+          PackageUtils.getVisibility(pkgBuilder.getBuildFileLabel(), value));
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java b/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
index df630ab..ace5f64 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
@@ -32,7 +32,6 @@
 import com.google.devtools.build.lib.syntax.ClassObject;
 import com.google.devtools.build.lib.syntax.Dict;
 import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.Location;
 import com.google.devtools.build.lib.syntax.Starlark;
 import com.google.devtools.build.lib.util.StringUtil;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
@@ -82,12 +81,9 @@
       extends StarlarkImplicitOutputsFunction {
 
     private final StarlarkCallbackHelper callback;
-    private final Location loc;
 
-    public StarlarkImplicitOutputsFunctionWithCallback(
-        StarlarkCallbackHelper callback, Location loc) {
+    public StarlarkImplicitOutputsFunctionWithCallback(StarlarkCallbackHelper callback) {
       this.callback = callback;
-      this.loc = loc;
     }
 
     @Override
@@ -123,18 +119,16 @@
           Iterable<String> substitutions =
               fromTemplates(entry.getValue()).getImplicitOutputs(eventHandler, map);
           if (Iterables.isEmpty(substitutions)) {
-            throw new EvalException(
-                loc,
-                String.format(
-                    "For attribute '%s' in outputs: %s",
-                    entry.getKey(), "Invalid placeholder(s) in template"));
+            throw Starlark.errorf(
+                "For attribute '%s' in outputs: Invalid placeholder(s) in template",
+                entry.getKey());
           }
 
           builder.put(entry.getKey(), Iterables.getOnlyElement(substitutions));
         }
         return builder.build();
-      } catch (IllegalArgumentException e) {
-        throw new EvalException(loc, e.getMessage());
+      } catch (IllegalArgumentException ex) {
+        throw new EvalException(ex);
       }
     }
   }
@@ -161,11 +155,8 @@
             fromUnsafeTemplates(ImmutableList.of(entry.getValue()));
         Iterable<String> substitutions = outputsFunction.getImplicitOutputs(eventHandler, map);
         if (Iterables.isEmpty(substitutions)) {
-          throw new EvalException(
-              String.format(
-                  "For attribute '%s' in outputs: %s",
-                  entry.getKey(), "Invalid placeholder(s) in template"));
-
+          throw Starlark.errorf(
+              "For attribute '%s' in outputs: Invalid placeholder(s) in template", entry.getKey());
         }
 
         builder.put(entry.getKey(), Iterables.getOnlyElement(substitutions));
@@ -542,9 +533,8 @@
     // Make sure all attributes are valid.
     for (String placeholder : parsedTemplate.attributeNames()) {
       if (rule.isConfigurable(placeholder)) {
-        throw new EvalException(
-            String.format(
-                "Attribute %s is configurable and cannot be used in outputs", placeholder));
+        throw Starlark.errorf(
+            "Attribute %s is configurable and cannot be used in outputs", placeholder);
       }
     }
 
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
index 9d7a818..eba39e4 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
@@ -356,7 +356,7 @@
           String name = kwarg.getKey();
           PackageArgument<?> pkgarg = packageArguments.get(name);
           if (pkgarg == null) {
-            throw new EvalException("unexpected keyword argument: " + name);
+            throw Starlark.errorf("unexpected keyword argument: %s", name);
           }
           pkgarg.convertAndProcess(pkgBuilder, loc, kwarg.getValue());
         }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java
index 1f0370e..f878ac8 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java
@@ -424,7 +424,7 @@
 
   private static class NotRepresentableException extends EvalException {
     NotRepresentableException(String msg) {
-      super(null, msg);
+      super(msg);
     }
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Type.java b/src/main/java/com/google/devtools/build/lib/packages/Type.java
index f240876..029bebf 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Type.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Type.java
@@ -277,11 +277,11 @@
     }
 
     public ConversionException(Type<?> type, Object value, @Nullable Object what) {
-      super(null, message(type, value, what));
+      super(message(type, value, what));
     }
 
     public ConversionException(String message) {
-      super(null, message);
+      super(message);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
index 7829667..35a9496 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
@@ -315,10 +315,10 @@
                   thread.getSemantics(),
                   thread.getCallStack());
           if (!WorkspaceGlobals.isLegalWorkspaceName(rule.getName())) {
-            throw new EvalException(
-                rule
-                    + "'s name field must be a legal workspace name;"
-                    + " workspace names may contain only A-Z, a-z, 0-9, '-', '_' and '.'");
+            throw Starlark.errorf(
+                "%s's name field must be a legal workspace name; workspace names may contain only"
+                    + " A-Z, a-z, 0-9, '-', '_' and '.'",
+                rule);
           }
         } catch (RuleFactory.InvalidRuleException
             | Package.NameConflictException
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
index 7864427..08468e8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
@@ -59,6 +59,7 @@
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Starlark;
 import com.google.devtools.build.lib.util.FileType;
 import com.google.devtools.build.lib.util.Pair;
 import com.google.devtools.build.lib.vfs.PathFragment;
@@ -834,7 +835,7 @@
 
     if (cppConfiguration.forcePic()) {
       if (unsupportedFeatures.contains(CppRuleClasses.SUPPORTS_PIC)) {
-        throw new EvalException(/* location= */ null, PIC_CONFIGURATION_ERROR);
+        throw new EvalException(PIC_CONFIGURATION_ERROR);
       }
       allRequestedFeaturesBuilder.add(CppRuleClasses.SUPPORTS_PIC);
     }
@@ -939,23 +940,20 @@
           toolchain.getFeatures().getFeatureConfiguration(allRequestedFeaturesBuilder.build());
       for (String feature : unsupportedFeatures) {
         if (featureConfiguration.isEnabled(feature)) {
-          throw new EvalException(
-              "The C++ toolchain '"
-                  + toolchain.getCcToolchainLabel()
-                  + "' unconditionally implies feature '"
-                  + feature
-                  + "', which is unsupported by this rule. "
-                  + "This is most likely a misconfiguration in the C++ toolchain.");
+          throw Starlark.errorf(
+              "The C++ toolchain '%s' unconditionally implies feature '%s', which is unsupported"
+                  + " by this rule. This is most likely a misconfiguration in the C++ toolchain.",
+              toolchain.getCcToolchainLabel(), feature);
         }
       }
       if (cppConfiguration.forcePic()
           && !featureConfiguration.isEnabled(CppRuleClasses.PIC)
           && !featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_PIC)) {
-        throw new EvalException(/* location= */ null, PIC_CONFIGURATION_ERROR);
+        throw new EvalException(PIC_CONFIGURATION_ERROR);
       }
       return featureConfiguration;
-    } catch (CollidingProvidesException e) {
-      throw new EvalException(/* location= */ null, e.getMessage());
+    } catch (CollidingProvidesException ex) {
+      throw new EvalException(ex);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java
index 11c6a54..63189d6 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java
@@ -38,7 +38,6 @@
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
 import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.Location;
 import com.google.devtools.build.lib.syntax.Starlark;
 import com.google.devtools.build.lib.util.Pair;
 import com.google.devtools.build.lib.util.StringUtil;
@@ -82,7 +81,7 @@
    */
   public static class ExpansionException extends EvalException {
     ExpansionException(String message) {
-      super(Location.BUILTIN, message);
+      super(message);
     }
   }
 
@@ -1073,7 +1072,7 @@
       ImmutableList.Builder<FlagSet> flagSetBuilder = ImmutableList.builder();
       for (CToolchain.FlagSet flagSet : actionConfig.getFlagSetList()) {
         if (!flagSet.getActionList().isEmpty()) {
-          throw new EvalException(String.format(FLAG_SET_WITH_ACTION_ERROR, configName));
+          throw Starlark.errorf(FLAG_SET_WITH_ACTION_ERROR, configName);
         }
 
         flagSetBuilder.add(new FlagSet(flagSet, ImmutableSet.of(actionName)));
@@ -1215,21 +1214,19 @@
         }
       }
       if (foundCategory == null) {
-        throw new EvalException(
-            String.format(
-                "Invalid toolchain configuration: Artifact category %s not recognized",
-                artifactNamePattern.getCategoryName()));
+        throw Starlark.errorf(
+            "Invalid toolchain configuration: Artifact category %s not recognized",
+            artifactNamePattern.getCategoryName());
       }
 
       String extension = artifactNamePattern.getExtension();
       if (!foundCategory.getAllowedExtensions().contains(extension)) {
-        throw new EvalException(
-            String.format(
-                "Unrecognized file extension '%s', allowed extensions are %s,"
-                    + " please check artifact_name_pattern configuration for %s in your CROSSTOOL.",
-                extension,
-                StringUtil.joinEnglishList(foundCategory.getAllowedExtensions(), "or", "'"),
-                foundCategory.getCategoryName()));
+        throw Starlark.errorf(
+            "Unrecognized file extension '%s', allowed extensions are %s,"
+                + " please check artifact_name_pattern configuration for %s in your CROSSTOOL.",
+            extension,
+            StringUtil.joinEnglishList(foundCategory.getAllowedExtensions(), "or", "'"),
+            foundCategory.getCategoryName());
       }
       this.artifactCategory = foundCategory;
       this.prefix = artifactNamePattern.getPrefix();
@@ -1636,11 +1633,10 @@
     Collection<String> names = new HashSet<>();
     for (CrosstoolSelectable selectable : selectables) {
       if (!names.add(selectable.getName())) {
-        throw new EvalException(
-            "Invalid toolchain configuration: feature or "
-                + "action config '"
-                + selectable.getName()
-                + "' was specified multiple times.");
+        throw Starlark.errorf(
+            "Invalid toolchain configuration: feature or action config '%s' was specified multiple"
+                + " times.",
+            selectable.getName());
       }
     }
   }
@@ -1650,11 +1646,9 @@
     Collection<String> actionNames = new HashSet<>();
     for (ActionConfig actionConfig : actionConfigs) {
       if (!actionNames.add(actionConfig.getActionName())) {
-        throw new EvalException(
-            "Invalid toolchain configuration: multiple action "
-                + "configs for action '"
-                + actionConfig.getActionName()
-                + "'");
+        throw Starlark.errorf(
+            "Invalid toolchain configuration: multiple action configs for action '%s'",
+            actionConfig.getActionName());
       }
     }
   }
@@ -1740,12 +1734,10 @@
   private CrosstoolSelectable getActivatableOrFail(String name, String reference)
       throws EvalException {
     if (!selectablesByName.containsKey(name)) {
-      throw new EvalException(
-          "Invalid toolchain configuration: feature '"
-              + name
-              + "', which is referenced from feature '"
-              + reference
-              + "', is not defined.");
+      throw Starlark.errorf(
+          "Invalid toolchain configuration: feature '%s', which is referenced from feature '%s',"
+              + " is not defined.",
+          name, reference);
     }
     return selectablesByName.get(name);
   }
@@ -1771,9 +1763,8 @@
       }
     }
     if (patternForCategory == null) {
-      throw new EvalException(
-          String.format(
-              MISSING_ARTIFACT_NAME_PATTERN_ERROR_TEMPLATE, artifactCategory.getCategoryName()));
+      throw Starlark.errorf(
+          MISSING_ARTIFACT_NAME_PATTERN_ERROR_TEMPLATE, artifactCategory.getCategoryName());
     }
 
     return output.getParentDirectory()
@@ -1794,9 +1785,8 @@
       }
     }
     if (patternForCategory == null) {
-      throw new EvalException(
-          String.format(
-              MISSING_ARTIFACT_NAME_PATTERN_ERROR_TEMPLATE, artifactCategory.getCategoryName()));
+      throw Starlark.errorf(
+          MISSING_ARTIFACT_NAME_PATTERN_ERROR_TEMPLATE, artifactCategory.getCategoryName());
     }
     return patternForCategory.getExtension();
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java
index 901e43a..b332a30 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java
@@ -38,6 +38,7 @@
 import com.google.devtools.build.lib.starlarkbuildapi.cpp.CcToolchainProviderApi;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Location;
+import com.google.devtools.build.lib.syntax.Starlark;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import javax.annotation.Nullable;
 
@@ -555,9 +556,9 @@
       throws EvalException {
     if (shouldStaticallyLinkCppRuntimes(featureConfiguration)) {
       if (staticRuntimeLinkInputs == null) {
-        throw new EvalException(
-            "Toolchain supports embedded runtimes, but didn't "
-                + "provide static_runtime_lib attribute.");
+        throw Starlark.errorf(
+            "Toolchain supports embedded runtimes, but didn't provide static_runtime_lib"
+                + " attribute.");
       }
       return staticRuntimeLinkInputs;
     } else {
@@ -588,8 +589,8 @@
     if (shouldStaticallyLinkCppRuntimes(featureConfiguration)) {
       if (dynamicRuntimeLinkInputs == null) {
         throw new EvalException(
-            "Toolchain supports embedded runtimes, but didn't "
-                + "provide dynamic_runtime_lib attribute.");
+            "Toolchain supports embedded runtimes, but didn't provide dynamic_runtime_lib"
+                + " attribute.");
       }
       return dynamicRuntimeLinkInputs;
     } else {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java
index 16c6bde..1e17a0d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java
@@ -38,6 +38,7 @@
 import com.google.devtools.build.lib.rules.cpp.CcToolchain.AdditionalBuildVariablesComputer;
 import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Starlark;
 import com.google.devtools.build.lib.util.Pair;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.EnumSet;
@@ -499,7 +500,7 @@
               });
       for (CppConfiguration.Tool tool : neededTools) {
         if (!toolPathsCollector.containsKey(tool.getNamePart())) {
-          throw new EvalException("Tool path for '" + tool.getNamePart() + "' is missing");
+          throw Starlark.errorf("Tool path for '%s' is missing", tool.getNamePart());
         }
       }
     }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainVariables.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainVariables.java
index 9b37d63..ae697de 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainVariables.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainVariables.java
@@ -34,6 +34,7 @@
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
 import com.google.devtools.build.lib.starlarkbuildapi.cpp.CcToolchainVariablesApi;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Starlark;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
@@ -267,14 +268,9 @@
      *     position in the string.
      */
     private void abort(String error) throws EvalException {
-      throw new EvalException(
-          "Invalid toolchain configuration: "
-              + error
-              + " at position "
-              + current
-              + " while parsing a flag containing '"
-              + value
-              + "'");
+      throw Starlark.errorf(
+          "Invalid toolchain configuration: %s at position %s while parsing a flag containing '%s'",
+          error, current, value);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java
index 312232a..5b44ce5 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java
@@ -28,7 +28,6 @@
 import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.StringSequenceBuilder;
 import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariablesExtension;
 import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.Location;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.List;
 import java.util.Map;
@@ -155,7 +154,7 @@
       if (usePic
           && !featureConfiguration.isEnabled(CppRuleClasses.PIC)
           && !featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_PIC)) {
-        throw new EvalException(Location.BUILTIN, CcCommon.PIC_CONFIGURATION_ERROR);
+        throw new EvalException(CcCommon.PIC_CONFIGURATION_ERROR);
       }
       return setupVariables(
           featureConfiguration,
@@ -223,7 +222,7 @@
     if (usePic
         && !featureConfiguration.isEnabled(CppRuleClasses.PIC)
         && !featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_PIC)) {
-      throw new EvalException(Location.BUILTIN, CcCommon.PIC_CONFIGURATION_ERROR);
+      throw new EvalException(CcCommon.PIC_CONFIGURATION_ERROR);
     }
     return setupVariables(
         featureConfiguration,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
index ea9e3fe..0359646 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
@@ -60,7 +60,6 @@
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.starlarkbuildapi.CommandLineArgsApi;
 import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.Location;
 import com.google.devtools.build.lib.syntax.Sequence;
 import com.google.devtools.build.lib.syntax.StarlarkList;
 import com.google.devtools.build.lib.util.DetailedExitCode;
@@ -484,8 +483,8 @@
   public Sequence<String> getStarlarkArgv() throws EvalException {
     try {
       return StarlarkList.immutableCopyOf(getArguments());
-    } catch (CommandLineExpansionException exception) {
-      throw new EvalException(Location.BUILTIN, exception);
+    } catch (CommandLineExpansionException ex) {
+      throw new EvalException(ex);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
index 0ef18a6..a5a4df8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
@@ -70,7 +70,6 @@
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
 import com.google.devtools.build.lib.starlarkbuildapi.CommandLineArgsApi;
 import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.Location;
 import com.google.devtools.build.lib.syntax.Sequence;
 import com.google.devtools.build.lib.syntax.StarlarkList;
 import com.google.devtools.build.lib.util.DetailedExitCode;
@@ -502,8 +501,8 @@
   public Sequence<String> getStarlarkArgv() throws EvalException {
     try {
       return StarlarkList.immutableCopyOf(getArguments());
-    } catch (CommandLineExpansionException exception) {
-      throw new EvalException(Location.BUILTIN, exception);
+    } catch (CommandLineExpansionException ex) {
+      throw new EvalException(ex);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStarlarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStarlarkCommon.java
index cd6671c..a7c9a60 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStarlarkCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStarlarkCommon.java
@@ -217,7 +217,7 @@
         }
         resultBuilder.addDirectDepProvidersFromStarlark(entry.getValue());
       } else {
-        throw new EvalException(String.format(BAD_KEY_ERROR, entry.getKey()));
+        throw Starlark.errorf(BAD_KEY_ERROR, entry.getKey());
       }
     }
     return resultBuilder.build();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java
index 0554273..f07fde2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java
@@ -1062,9 +1062,8 @@
 
     /** Return an EvalException for having a bad key in the direct dependency provider. */
     private static <E> EvalException badDirectDependencyKeyError(Key<E> key) {
-      return new EvalException(
-          String.format(
-              AppleStarlarkCommon.BAD_DIRECT_DEPENDENCY_KEY_ERROR, key.getStarlarkKeyName()));
+      return Starlark.errorf(
+          AppleStarlarkCommon.BAD_DIRECT_DEPENDENCY_KEY_ERROR, key.getStarlarkKeyName());
     }
 
     /**
@@ -1194,8 +1193,8 @@
       if (DEPRECATED_KEYS.contains(key)) {
         if (getStarlarkSemantics().incompatibleObjcProviderRemoveCompileInfo()) {
           if (!KEYS_FOR_DIRECT.contains(key)) {
-            throw new EvalException(
-                String.format(AppleStarlarkCommon.DEPRECATED_KEY_ERROR, key.getStarlarkKeyName()));
+            throw Starlark.errorf(
+                AppleStarlarkCommon.DEPRECATED_KEY_ERROR, key.getStarlarkKeyName());
           }
         } else {
           if (!addCompileElementsFromStarlark(key, starlarkToAdd)) {
@@ -1234,8 +1233,7 @@
         ImmutableList.Builder<PathFragment> frameworkSearchPaths = ImmutableList.builder();
         for (PathFragment framework : frameworks) {
           if (!framework.getSafePathString().endsWith(FRAMEWORK_SUFFIX)) {
-            throw new EvalException(
-                String.format(AppleStarlarkCommon.BAD_FRAMEWORK_PATH_ERROR, framework));
+            throw Starlark.errorf(AppleStarlarkCommon.BAD_FRAMEWORK_PATH_ERROR, framework);
           }
           frameworkSearchPaths.add(framework.getParentDirectory());
         }
@@ -1276,15 +1274,13 @@
     @SuppressWarnings("unchecked")
     void addProvidersFromStarlark(Object toAdd) throws EvalException {
       if (!(toAdd instanceof Iterable)) {
-        throw new EvalException(
-            String.format(AppleStarlarkCommon.BAD_PROVIDERS_ITER_ERROR, Starlark.type(toAdd)));
+        throw Starlark.errorf(AppleStarlarkCommon.BAD_PROVIDERS_ITER_ERROR, Starlark.type(toAdd));
       } else {
         Iterable<Object> toAddIterable = (Iterable<Object>) toAdd;
         for (Object toAddObject : toAddIterable) {
           if (!(toAddObject instanceof ObjcProvider)) {
-            throw new EvalException(
-                String.format(
-                    AppleStarlarkCommon.BAD_PROVIDERS_ELEM_ERROR, Starlark.type(toAddObject)));
+            throw Starlark.errorf(
+                AppleStarlarkCommon.BAD_PROVIDERS_ELEM_ERROR, Starlark.type(toAddObject));
           } else {
             ObjcProvider objcProvider = (ObjcProvider) toAddObject;
             this.addTransitiveAndPropagate(objcProvider);
@@ -1302,15 +1298,13 @@
     @SuppressWarnings("unchecked")
     void addDirectDepProvidersFromStarlark(Object toAdd) throws EvalException {
       if (!(toAdd instanceof Iterable)) {
-        throw new EvalException(
-            String.format(AppleStarlarkCommon.BAD_PROVIDERS_ITER_ERROR, Starlark.type(toAdd)));
+        throw Starlark.errorf(AppleStarlarkCommon.BAD_PROVIDERS_ITER_ERROR, Starlark.type(toAdd));
       } else {
         Iterable<Object> toAddIterable = (Iterable<Object>) toAdd;
         for (Object toAddObject : toAddIterable) {
           if (!(toAddObject instanceof ObjcProvider)) {
-            throw new EvalException(
-                String.format(
-                    AppleStarlarkCommon.BAD_PROVIDERS_ELEM_ERROR, Starlark.type(toAddObject)));
+            throw Starlark.errorf(
+                AppleStarlarkCommon.BAD_PROVIDERS_ELEM_ERROR, Starlark.type(toAddObject));
           } else {
             this.addAsDirectDeps((ObjcProvider) toAddObject);
           }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PyStructUtils.java b/src/main/java/com/google/devtools/build/lib/rules/python/PyStructUtils.java
index 353ce09..c2dc8ee 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PyStructUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PyStructUtils.java
@@ -87,7 +87,7 @@
     if (fieldValue == null) {
       fieldValue = DEFAULTS.get(fieldName);
       if (fieldValue == null) {
-        throw new EvalException(String.format("'py' provider missing '%s' field", fieldName));
+        throw Starlark.errorf("'py' provider missing '%s' field", fieldName);
       }
     }
     return fieldValue;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
index a0f6127..e66fe4e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
@@ -41,7 +41,7 @@
 import com.google.devtools.build.lib.skyframe.PackageLookupValue;
 import com.google.devtools.build.lib.skyframe.PrecomputedValue;
 import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.Location;
+import com.google.devtools.build.lib.syntax.Starlark;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
@@ -135,7 +135,7 @@
    */
   protected static class RepositoryMissingDependencyException extends EvalException {
     RepositoryMissingDependencyException() {
-      super(Location.BUILTIN, "Internal exception");
+      super("Internal exception");
     }
   }
 
@@ -290,7 +290,7 @@
       if (pkgLookupValue == PackageLookupValue.NO_BUILD_FILE_VALUE) {
         message = PackageLookupFunction.explainNoBuildFileValue(label.getPackageIdentifier(), env);
       }
-      throw new EvalException("Unable to load package for " + label + ": " + message);
+      throw Starlark.errorf("Unable to load package for %s: %s", label, message);
     }
 
     // And now for the file
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/WorkspaceAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/rules/repository/WorkspaceAttributeMapper.java
index 61c5593..8dbfac1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/WorkspaceAttributeMapper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/WorkspaceAttributeMapper.java
@@ -22,6 +22,7 @@
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.packages.Type;
 import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Starlark;
 import javax.annotation.Nullable;
 
 /**
@@ -49,8 +50,8 @@
     Object value = getObject(attributeName);
     try {
       return type.cast(value);
-    } catch (ClassCastException e) {
-      throw new EvalException(rule.getLocation(), e.getMessage());
+    } catch (ClassCastException ex) {
+      throw new EvalException(ex);
     }
   }
 
@@ -61,12 +62,10 @@
   public Object getObject(String attributeName) throws EvalException {
     Object value = rule.getAttributeContainer().getAttr(checkNotNull(attributeName));
     if (value instanceof SelectorList) {
-      throw new EvalException(
-          rule.getLocation(),
-          String.format(
-              "got value of type 'select' for attribute '%s' of %s rule '%s'; select may not be "
-                  + "used in repository rules",
-              attributeName, rule.getRuleClass(), rule.getName()));
+      throw Starlark.errorf(
+          "got value of type 'select' for attribute '%s' of %s rule '%s'; select may not be used"
+              + " in repository rules",
+          attributeName, rule.getRuleClass(), rule.getName());
     }
     return value;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsFunction.java
index dd752e0..3e4874b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsFunction.java
@@ -24,8 +24,8 @@
 import com.google.devtools.build.lib.skyframe.BzlLoadFunction.BzlLoadFailedException;
 import com.google.devtools.build.lib.syntax.Dict;
 import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.Location;
 import com.google.devtools.build.lib.syntax.Module;
+import com.google.devtools.build.lib.syntax.Starlark;
 import com.google.devtools.build.skyframe.RecordingSkyFunctionEnvironment;
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyFunctionException;
@@ -83,11 +83,7 @@
    * SkyKey.
    */
   private static final Label EXPORTS_ENTRYPOINT =
-      Label.parseAbsoluteUnchecked("@builtins//:exports.bzl");
-
-  /** Same as above, as a {@link Location} for errors. */
-  private static final Location EXPORTS_ENTRYPOINT_LOC =
-      new Location(EXPORTS_ENTRYPOINT.getCanonicalForm(), /*line=*/ 0, /*column=*/ 0);
+      Label.parseAbsoluteUnchecked("@builtins//:exports.bzl"); // unused
 
   /**
    * Key for loading exports.bzl. {@code keyForBuiltins} (as opposed to {@code keyForBuild} ensures
@@ -202,7 +198,6 @@
               ruleClassProvider, packageFactory, exportedToplevels, exportedRules);
       return new StarlarkBuiltinsValue(predeclared, exportedToJava, transitiveDigest);
     } catch (EvalException ex) {
-      ex = new EvalException(EXPORTS_ENTRYPOINT_LOC, ex.getMessage());
       throw BuiltinsFailedException.errorApplyingExports(ex);
     }
   }
@@ -309,7 +304,7 @@
       throws EvalException {
     Object value = module.get(dictName);
     if (value == null) {
-      throw new EvalException(String.format("expected a '%s' dictionary to be defined", dictName));
+      throw Starlark.errorf("expected a '%s' dictionary to be defined", dictName);
     }
     return ImmutableMap.copyOf(Dict.cast(value, String.class, Object.class, dictName + " dict"));
   }
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java b/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java
index 9583c4e..04c9a40 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java
@@ -98,7 +98,7 @@
     } else if (end instanceof Integer) {
       stop = EvalUtils.toIndex((Integer) end, str.length());
     } else {
-      throw new EvalException("expected int for " + what + ", got " + Starlark.type(end));
+      throw Starlark.errorf("expected int for %s, got %s", what, Starlark.type(end));
     }
     if (start >= stop) {
       return "";