bazelbuild/bazel · error · OptionsParsingException

Flag policy for flag '%s' does not have an operation

Error message

Flag policy for flag '%s' does not have an operation

What it means

Thrown by InvocationPolicyEnforcer when a FlagPolicy proto in the invocation policy has OPERATION_NOT_SET — i.e. a flag_policy entry names a flag but contains no operation (set_value, use_default, disallow_values, etc.). The policy is structurally incomplete, so the enforcer refuses it via PolicyOperationNotSetException (an OptionsParsingException).

Source

Thrown at src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java:186

          break;

        case DISALLOW_VALUES:
          DisallowValues disallowValues = flagPolicy.policy.getDisallowValues();
          FilterValueOperation.DisallowValueOperation disallowValueOperation =
              new FilterValueOperation.DisallowValueOperation(loglevel, conversionContext);
          disallowValueOperation.apply(
              parser,
              flagPolicy.origin,
              disallowValues.getDisallowedValuesList(),
              disallowValues.hasNewValue() ? disallowValues.getNewValue() : null,
              disallowValues.hasUseDefault(),
              valueDescription,
              flagPolicy.description,
              invocationPolicyFlagListBuilder);
          break;

        case OPERATION_NOT_SET:
          throw new PolicyOperationNotSetException(flagName);

        default:
          logger.atWarning().log(
              "Unknown operation '%s' from invocation policy for flag '%s'",
              flagPolicy.policy.getOperationCase(), flagName);
          break;
      }
    }
  }

  private static class PolicyOperationNotSetException extends OptionsParsingException {
    PolicyOperationNotSetException(String flagName) {
      super(String.format("Flag policy for flag '%s' does not " + "have an operation", flagName));
    }
  }

  private static boolean policyApplies(FlagPolicy policy, ImmutableSet<String> applicableCommands) {
    // If the commands list is empty, then the policy applies to all commands.

View on GitHub (pinned to e6e199d060)

Solutions

  1. Add a concrete operation to the offending flagPolicy entry: set_value, use_default, allow_values, or disallow_values.
  2. Validate the policy file against the InvocationPolicy proto schema before deploying (parse it with the protobuf and assert getOperationCase() != OPERATION_NOT_SET).
  3. Check JSON field naming: proto JSON uses lowerCamelCase (setValue) unless json_name is customized — a misnamed field silently leaves the operation unset.
  4. Use bazel's policy parsing dry-run (bazel with --invocation_policy against a no-op command) to catch structural errors before rolling out.

Example fix

// before
{"flagPolicy":[{"flagName":"compilation_mode"}]}

// after
{"flagPolicy":[{"flagName":"compilation_mode","setValue":{"flagValue":["opt"],"behavior":"ALLOW_OVERRIDES"}}]}
Defensive patterns

Strategy: validation

Validate before calling

// Structural lint of a policy file before deployment
InvocationPolicy policy = parsePolicyJson(json);
for (FlagPolicy fp : policy.getFlagPoliciesList()) {
  if (fp.getOperationCase() == FlagPolicy.OperationCase.OPERATION_NOT_SET) {
    throw new IllegalStateException("Policy entry for '" + fp.getFlagName() + "' has no operation");
  }
}

Try / catch

Catch OptionsParsingException (PolicyOperationNotSetException) at policy enforcement; report the flag name from the message and fix the policy JSON at the named entry.

Prevention

When it happens

Trigger: Writing a --invocation_policy JSON/proto file with a flagPolicy entry that has flagName but no operation submessage, e.g. {"flagPolicy": [{"flagName": "compilation_mode"}]}. Also reachable if a policy generator emits an entry with all fields defaulted.

Common situations: Hand-editing invocation policy files and forgetting the operation block, policy YAML/JSON templates with a commented-out operation, org-wide policy tooling that emits empty entries when a feature flag is disabled, protobuf field-name typos (e.g. setValue vs set_value in JSON) making the operation parse as unset.

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/57843ff93c8ee5e6. Report an issue: GitHub.