{"record":{"id":"57843ff93c8ee5e6","repo":"bazelbuild/bazel","slug":"flag-policy-for-flag-s-does-not-have-an-operati","errorCode":null,"errorMessage":"Flag policy for flag '%s' does not have an operation","messagePattern":"Flag policy for flag '(.+?)' does not have an operation","errorType":"validation","errorClass":"OptionsParsingException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java","lineNumber":186,"sourceCode":"          break;\n\n        case DISALLOW_VALUES:\n          DisallowValues disallowValues = flagPolicy.policy.getDisallowValues();\n          FilterValueOperation.DisallowValueOperation disallowValueOperation =\n              new FilterValueOperation.DisallowValueOperation(loglevel, conversionContext);\n          disallowValueOperation.apply(\n              parser,\n              flagPolicy.origin,\n              disallowValues.getDisallowedValuesList(),\n              disallowValues.hasNewValue() ? disallowValues.getNewValue() : null,\n              disallowValues.hasUseDefault(),\n              valueDescription,\n              flagPolicy.description,\n              invocationPolicyFlagListBuilder);\n          break;\n\n        case OPERATION_NOT_SET:\n          throw new PolicyOperationNotSetException(flagName);\n\n        default:\n          logger.atWarning().log(\n              \"Unknown operation '%s' from invocation policy for flag '%s'\",\n              flagPolicy.policy.getOperationCase(), flagName);\n          break;\n      }\n    }\n  }\n\n  private static class PolicyOperationNotSetException extends OptionsParsingException {\n    PolicyOperationNotSetException(String flagName) {\n      super(String.format(\"Flag policy for flag '%s' does not \" + \"have an operation\", flagName));\n    }\n  }\n\n  private static boolean policyApplies(FlagPolicy policy, ImmutableSet<String> applicableCommands) {\n    // If the commands list is empty, then the policy applies to all commands.","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/src/main/java/com/google/devtools/common/options/InvocationPolicyEnforcer.java#L168-L204","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add a concrete operation to the offending flagPolicy entry: set_value, use_default, allow_values, or disallow_values.","Validate the policy file against the InvocationPolicy proto schema before deploying (parse it with the protobuf and assert getOperationCase() != OPERATION_NOT_SET).","Check JSON field naming: proto JSON uses lowerCamelCase (setValue) unless json_name is customized — a misnamed field silently leaves the operation unset.","Use bazel's policy parsing dry-run (bazel with --invocation_policy against a no-op command) to catch structural errors before rolling out."],"exampleFix":"// before\n{\"flagPolicy\":[{\"flagName\":\"compilation_mode\"}]}\n\n// after\n{\"flagPolicy\":[{\"flagName\":\"compilation_mode\",\"setValue\":{\"flagValue\":[\"opt\"],\"behavior\":\"ALLOW_OVERRIDES\"}}]}","handlingStrategy":"validation","validationCode":"// Structural lint of a policy file before deployment\nInvocationPolicy policy = parsePolicyJson(json);\nfor (FlagPolicy fp : policy.getFlagPoliciesList()) {\n  if (fp.getOperationCase() == FlagPolicy.OperationCase.OPERATION_NOT_SET) {\n    throw new IllegalStateException(\"Policy entry for '\" + fp.getFlagName() + \"' has no operation\");\n  }\n}","typeGuard":null,"tryCatchPattern":"Catch OptionsParsingException (PolicyOperationNotSetException) at policy enforcement; report the flag name from the message and fix the policy JSON at the named entry.","preventionTips":["Always include exactly one operation block per flagPolicy entry","Use proto JSON camelCase field names (setValue, useDefault) to avoid silent drops","Lint policy files in CI with a protobuf parse + operation-case assertion"],"tags":["invocation-policy","protobuf","options-parsing","bazel"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}