bytebase/bytebase · error

expect bool result for masking rule

Error message

expect bool result for masking rule

What it means

The masking rule expression evaluated but its result cannot be converted to a Go bool via ConvertToNative(reflect.TypeFor[bool]()). Masking rules must be boolean conditions; an expression returning a string, int, or list triggers this. It signals the stored expression has the wrong return type, not an evaluation malfunction.

Source

Thrown at backend/api/v1/masking_evaluator.go:314

	maskingRulePolicyEnv, err := cel.NewEnv(common.MaskingRulePolicyCELAttributes...)
	if err != nil {
		return false, errors.Wrapf(err, "failed to create CEL environment for masking rule policy")
	}
	ast, issues := maskingRulePolicyEnv.Compile(expression)
	if issues != nil && issues.Err() != nil {
		return false, errors.Wrapf(issues.Err(), "failed to get the ast of CEL program for masking rule")
	}
	prg, err := maskingRulePolicyEnv.Program(ast)
	if err != nil {
		return false, errors.Wrapf(err, "failed to create CEL program for masking rule")
	}
	out, _, err := prg.Eval(attributes)
	if err != nil {
		return false, errors.Wrapf(err, "failed to eval CEL program for masking rule")
	}
	val, err := out.ConvertToNative(reflect.TypeFor[bool]())
	if err != nil {
		return false, errors.Wrap(err, "expect bool result for masking rule")
	}
	boolVar, ok := val.(bool)
	if !ok {
		return false, errors.Wrap(err, "expect bool result for masking rule")
	}
	return boolVar, nil
}

func evaluateQueryExportPolicyCondition(expression string, attributes map[string]any) (bool, error) {
	if expression == "" {
		return true, nil
	}
	env, err := cel.NewEnv(common.IAMPolicyConditionCELAttributes...)
	if err != nil {
		return false, err
	}
	ast, issues := env.Compile(expression)
	if issues != nil && issues.Err() != nil {

View on GitHub (pinned to 1870550677)

Solutions

  1. Rewrite the stored masking rule so it yields a boolean (complete comparison, logical expression, or has()/matches() predicate)
  2. Enforce bool output at save time: compile with a cel.Checks/OutputType(cel.BoolType) expectation and reject non-bool rules in the API
  3. Use common.ValidateMaskingRuleCELExpr when importing or editing rules to catch wrong return types before persistence

Example fix

// before (rule expression)
resource.database_id
// after
resource.database_id == "db-prod"
Defensive patterns

Strategy: validation

Validate before calling

ast, issues := env.Compile(expr)
if issues != nil && issues.Err() != nil { return issues.Err() }
if ast.OutputType() != cel.BoolType {
	return errors.New("masking rule must evaluate to a boolean")
}

Type guard

func maskingRuleIsBool(env *cel.Env, expr string) bool {
	ast, issues := env.Compile(expr)
	if issues != nil && issues.Err() != nil { return false }
	return ast.OutputType() == cel.BoolType
}

Try / catch

pass, err := evaluateMaskingRulePolicyCondition(expr, attrs)
if err != nil {
	return false, errors.Wrapf(err, "masking rule %q must be boolean", expr)
}

Prevention

When it happens

Trigger: evaluateMaskingRulePolicyCondition at backend/api/v1/masking_evaluator.go:312-314: out.ConvertToNative fails because the masking rule's top-level expression is a non-bool value (e.g. a bare `resource.database_id` or an arithmetic/string expression).

Common situations: Admin pasted a non-boolean expression (e.g. a projection like `resource.column.name`) into the masking rule field; a truncated expression lost its comparison operator (`resource.database_id == "x"` saved as `resource.database_id == "x" &&` then 'fixed' by deleting the operand side).

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06). Data as JSON: /api/errors/8250457839cb856e. Report an issue: GitHub.