{"record":{"id":"5dc674b726ea604e","repo":"bytebase/bytebase","slug":"export-value-must-be-a-boolean","errorCode":null,"errorMessage":"export value must be a boolean","messagePattern":"export value must be a boolean","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/store/access_grant.go","lineNumber":453,"sourceCode":"\t\t\t\t\t\treturn nil, errors.Wrapf(err, \"invalid issue name %q\", issueStr)\n\t\t\t\t\t}\n\t\t\t\t\treturn qb.Q().Space(\"(access_grant.payload->>'issueId')::bigint = ?\", issueUID), nil\n\t\t\t\tcase \"target\":\n\t\t\t\t\ttargetStr, ok := value.(string)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\treturn nil, errors.Errorf(\"target value must be a string\")\n\t\t\t\t\t}\n\t\t\t\t\treturn qb.Q().Space(\"access_grant.payload->'targets' @> jsonb_build_array(to_jsonb(?::text))\", targetStr), nil\n\t\t\t\tcase \"unmask\":\n\t\t\t\t\tboolVal, ok := value.(bool)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\treturn nil, errors.Errorf(\"unmask value must be a boolean\")\n\t\t\t\t\t}\n\t\t\t\t\treturn qb.Q().Space(\"COALESCE((access_grant.payload->>'unmask')::boolean, false) = ?\", boolVal), nil\n\t\t\t\tcase \"export\":\n\t\t\t\t\tboolVal, ok := value.(bool)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\treturn nil, errors.Errorf(\"export value must be a boolean\")\n\t\t\t\t\t}\n\t\t\t\t\treturn qb.Q().Space(\"COALESCE((access_grant.payload->>'export')::boolean, false) = ?\", boolVal), nil\n\t\t\t\tdefault:\n\t\t\t\t\treturn nil, errors.Errorf(\"unsupported variable %q\", variable)\n\t\t\t\t}\n\t\t\tcase celoverloads.Contains:\n\t\t\t\tcall := expr.AsCall()\n\t\t\t\ttarget := call.Target()\n\t\t\t\tif target.Kind() != celast.IdentKind {\n\t\t\t\t\treturn nil, errors.Errorf(\"contains target must be an identifier\")\n\t\t\t\t}\n\t\t\t\tvariable := target.AsIdent()\n\t\t\t\tif variable != \"query\" {\n\t\t\t\t\treturn nil, errors.Errorf(\"contains is not supported on field %q\", variable)\n\t\t\t\t}\n\t\t\t\targs := call.Args()\n\t\t\t\tif len(args) != 1 || args[0].Kind() != celast.LiteralKind {\n\t\t\t\t\treturn nil, errors.Errorf(\"contains requires a single string literal argument\")","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/store/access_grant.go#L435-L471","documentation":"For `export == <value>` the compiler asserts a Go bool literal, producing the predicate COALESCE((payload->>'export')::boolean, false) = ?. Non-bool literals (strings, numbers) are rejected with this error.","triggerScenarios":"ListAccessGrants filter like `export == \"true\"`, `export == 0`, or `export == null`.","commonSituations":"Same as the unmask case: string-serialized booleans from JSON/env config, over-quoted templated filters, and client SDKs that stringify bools.","solutions":["Write the filter with bare booleans: `export == true` / `export == false`.","Fix the value source so booleans stay typed (JSON bool, Go bool) rather than \"true\"/\"false\" strings.","Format bool values with %t, not %q or %v on a string, when generating the filter."],"exampleFix":"// before\nfilter := fmt.Sprintf(\"export == %v\", exportStr) // \"true\"\n// after\nfilter := fmt.Sprintf(\"export == %t\", exportBool)","handlingStrategy":"type-guard","validationCode":"if _, ok := exportValue.(bool); !ok {\n    return fmt.Errorf(\"export filter value must be a bool, got %T\", exportValue)\n}","typeGuard":"func isBool(v any) bool {\n    _, ok := v.(bool)\n    return ok\n}","tryCatchPattern":"if _, err := store.ListAccessGrants(ctx, filter); err != nil {\n    if strings.Contains(err.Error(), \"export value must be a boolean\") {\n        return status.Error(codes.InvalidArgument, \"export must be true or false, unquoted\")\n    }\n    return err\n}","preventionTips":["Keep bools typed end-to-end (JSON bool -> Go bool -> CEL bool)","Use %t formatting for booleans in generated filter strings","Reject \"true\"/\"false\" strings at the config boundary","Unit-test each boolean filter field"],"tags":["cel","filter","type-mismatch","boolean"],"backgroundTag":"type-mismatch","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}