bytebase/bytebase · error
unsupported variable %q
Error message
unsupported variable %q
What it means
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.
Source
Thrown at backend/store/access_grant.go:457
targetStr, ok := value.(string)
if !ok {
return nil, errors.Errorf("target value must be a string")
}
return qb.Q().Space("access_grant.payload->'targets' @> jsonb_build_array(to_jsonb(?::text))", targetStr), nil
case "unmask":
boolVal, ok := value.(bool)
if !ok {
return nil, errors.Errorf("unmask value must be a boolean")
}
return qb.Q().Space("COALESCE((access_grant.payload->>'unmask')::boolean, false) = ?", boolVal), nil
case "export":
boolVal, ok := value.(bool)
if !ok {
return nil, errors.Errorf("export value must be a boolean")
}
return qb.Q().Space("COALESCE((access_grant.payload->>'export')::boolean, false) = ?", boolVal), nil
default:
return nil, errors.Errorf("unsupported variable %q", variable)
}
case celoverloads.Contains:
call := expr.AsCall()
target := call.Target()
if target.Kind() != celast.IdentKind {
return nil, errors.Errorf("contains target must be an identifier")
}
variable := target.AsIdent()
if variable != "query" {
return nil, errors.Errorf("contains is not supported on field %q", variable)
}
args := call.Args()
if len(args) != 1 || args[0].Kind() != celast.LiteralKind {
return nil, errors.Errorf("contains requires a single string literal argument")
}
value, ok := args[0].AsLiteral().Value().(string)
if !ok {
return nil, errors.Errorf("contains argument must be a string")View on GitHub (pinned to 1870550677)
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.
Example fix
// before filter := "create_time > \"2024-01-01\"" // after filter := "status == \"ACTIVE\"" // only documented fields are supported
Defensive patterns
Strategy: validation
Validate before calling
var supportedFields = map[string]bool{
"name": true, "creator": true, "status": true, "query": true,
"issue": true, "target": true, "unmask": true, "export": true,
}
// Extract the leading identifier of each clause and check it before sending.
if !supportedFields[field] {
return fmt.Errorf("field %q is not filterable on access grants", field)
} Try / catch
if _, err := store.ListAccessGrants(ctx, filter); err != nil {
if strings.Contains(err.Error(), "unsupported variable") {
return status.Error(codes.InvalidArgument, err.Error())
}
return err
} Prevention
- 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
When it happens
Trigger: ListAccessGrants filter referencing a non-existent or not-filterable field, e.g. `create_time == "..."`, `project == "p"`, or a misspelled field like `statuz == "ACTIVE"`.
Common situations: 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.
Understand the failure class
Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.
Related errors
- invalid empty creator identifier
- CodeInvalidArgument
- CodeInvalidArgument
- failed to extract category
- unsupported filter variable: %s
AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06).
Data as JSON: /api/errors/3462e272d5c7faf7.
Report an issue: GitHub.