{"record":{"id":"3462e272d5c7faf7","repo":"bytebase/bytebase","slug":"unsupported-variable-q","errorCode":null,"errorMessage":"unsupported variable %q","messagePattern":"unsupported variable %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/store/access_grant.go","lineNumber":457,"sourceCode":"\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\")\n\t\t\t\t}\n\t\t\t\tvalue, ok := args[0].AsLiteral().Value().(string)\n\t\t\t\tif !ok {\n\t\t\t\t\treturn nil, errors.Errorf(\"contains argument must be a string\")","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/store/access_grant.go#L439-L475","documentation":"The CEL equality branch of the access-grant filter compiler only recognizes the variables name, creator, status, query, issue, target, unmask, and export. Any other identifier on the left side of `==` falls through to the default case and returns this error naming the unsupported variable.","triggerScenarios":"ListAccessGrants filter referencing a non-existent or not-filterable field, e.g. `create_time == \"...\"`, `project == \"p\"`, or a misspelled field like `statuz == \"ACTIVE\"`.","commonSituations":"Typos in hand-written filters, copying filter strings from other resources (issues, audit logs) that support different fields, and clients assuming all proto fields are filterable.","solutions":["Use only the supported fields: name, creator, status, query, issue, target, unmask, export.","Fix the field-name typo in the filter.","Check the ListAccessGrantsRequest filter documentation for the allowed fields before adding new ones.","If a new field is genuinely needed, extend the compiler with a new case and SQL predicate."],"exampleFix":"// before\nfilter := \"create_time > \\\"2024-01-01\\\"\"\n// after\nfilter := \"status == \\\"ACTIVE\\\"\" // only documented fields are supported","handlingStrategy":"validation","validationCode":"var supportedFields = map[string]bool{\n    \"name\": true, \"creator\": true, \"status\": true, \"query\": true,\n    \"issue\": true, \"target\": true, \"unmask\": true, \"export\": true,\n}\n// Extract the leading identifier of each clause and check it before sending.\nif !supportedFields[field] {\n    return fmt.Errorf(\"field %q is not filterable on access grants\", field)\n}","typeGuard":null,"tryCatchPattern":"if _, err := store.ListAccessGrants(ctx, filter); err != nil {\n    if strings.Contains(err.Error(), \"unsupported variable\") {\n        return status.Error(codes.InvalidArgument, err.Error())\n    }\n    return err\n}","preventionTips":["Keep the supported-field list documented next to the filter parser","Never reuse filter strings across different resources","Validate field names at the API layer before invoking the store","Add a table-driven test enumerating supported and unsupported fields"],"tags":["cel","filter","unsupported-field","validation"],"backgroundTag":"invalid-query-parameter","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"}