{"record":{"id":"fa227f15cecae01d","repo":"bazelbuild/bazel","slug":"invocation-policy-is-applied-after-config-expans","errorCode":null,"errorMessage":"Invocation policy is applied after --config expansion, changing config values now would have no effect and is disallowed to prevent confusion. Please remove the following policy : ","messagePattern":"Invocation policy is applied after --config expansion, changing config values now would have no effect and is disallowed to prevent confusion\\. Please remove the following policy : ","errorType":"exception","errorClass":"OptionsParsingException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java","lineNumber":254,"sourceCode":"      throws OptionsParsingException {\n    if (invocationPolicy == null) {\n      return ImmutableList.of();\n    }\n\n    ImmutableSet<String> commandAndParentCommands =\n        Preconditions.checkNotNull(\n            CommandNameCache.CommandNameCacheInstance.INSTANCE.get(command),\n            \"Command %s does not exist\",\n            command);\n\n    // Expand all policies to transfer policies on expansion flags to policies on the child flags.\n    List<FlagPolicyWithContext> expandedPolicies = new ArrayList<>();\n    OptionPriority nextPriority =\n        OptionPriority.lowestOptionPriorityAtCategory(PriorityCategory.INVOCATION_POLICY);\n    for (FlagPolicy policy : invocationPolicy.getFlagPoliciesList()) {\n      // Explicitly disallow --config in invocation policy.\n      if (policy.getFlagName().equals(\"config\")) {\n        throw new OptionsParsingException(\n            \"Invocation policy is applied after --config expansion, changing config values now \"\n                + \"would have no effect and is disallowed to prevent confusion. Please remove the \"\n                + \"following policy : \"\n                +\n            policy\n            );\n      }\n\n      // These policies are high-level, before expansion, and so are not the implicitDependents or\n      // expansions of any other flag, other than in an obtuse sense from --invocation_policy.\n      OptionPriority currentPriority = nextPriority;\n      OptionInstanceOrigin origin =\n          new OptionInstanceOrigin(currentPriority, INVOCATION_POLICY_SOURCE, null, null);\n      nextPriority = OptionPriority.nextOptionPriority(currentPriority);\n      if (!policyApplies(policy, commandAndParentCommands)) {\n        // Only keep and expand policies that are applicable to the current command.\n        continue;\n      }","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java#L236-L272","documentation":"Thrown when an invocation policy attempts to set the special --config flag. Invocation policies are enforced after --config expansion has already happened, so a policy on --config would silently do nothing; the enforcer throws to make this no-op explicit and prevent user confusion.","triggerScenarios":"Any invocation policy file containing {\"flagName\": \"config\", ...} passed via --invocation_policy (or enforced org-wide). The check is a literal string equality on the flag name 'config'.","commonSituations":"Org policy authors trying to force/forbid specific configurations through --config instead of the underlying flags, porting .bazelrc config sections into policy files, tooling that auto-generates policy from a list of 'locked' flags that happens to include --config.","solutions":["Remove the config entry from the policy file.","Express the intent as policies on the flags that --config expands to (e.g. instead of forcing --config=release, set compilation_mode, strip, etc. directly).","If --config must be controlled, do it via .bazelrc rules or wrapper scripts before invocation, not via invocation policy.","Expand the config locally (bazel's --announce_rc or config expansion docs) to find which child flags to target."],"exampleFix":"// before\n{\"flagPolicy\":[{\"flagName\":\"config\",\"setValue\":{\"flagValue\":[\"release\"]}}]}\n\n// after\n{\"flagPolicy\":[{\"flagName\":\"compilation_mode\",\"setValue\":{\"flagValue\":[\"opt\"]}}]}","handlingStrategy":"validation","validationCode":"// Reject policies touching --config before deployment\nboolean touchesConfig(InvocationPolicy p) {\n  return p.getFlagPoliciesList().stream()\n      .anyMatch(fp -> fp.getFlagName().equals(\"config\"));\n}","typeGuard":null,"tryCatchPattern":"Catch OptionsParsingException at startup of the command; treat it as a policy-authoring bug — remove the config entry rather than catching and continuing.","preventionTips":["Policy the underlying flags, never --config","Expand configs locally first to learn which child flags to target","Add 'config' to a deny-list in policy linters"],"tags":["invocation-policy","config-expansion","bazel","policy"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}