bytebase/bytebase · error

status value must be a string

Error message

status value must be a string

What it means

The access-grant CEL filter compiler in backend/store/access_grant.go converts a CEL filter expression into SQL. When it encounters `status == <value>` and the CEL literal is not a Go string, it refuses to build the predicate and returns this error. It guards the typed conversion before the value reaches getAccessGrantStatusFilter.

Source

Thrown at backend/store/access_grant.go:400

					_, accessGrantID, err := common.GetProjectIDAccessGrantID(nameStr)
					if err != nil {
						return nil, errors.Wrapf(err, "invalid access grant name %q", nameStr)
					}
					return qb.Q().Space("access_grant.id = ?", accessGrantID), nil
				case "creator":
					creatorStr, ok := value.(string)
					if !ok {
						return nil, errors.Errorf("creator value must be a string")
					}
					if !strings.HasPrefix(creatorStr, "users/") {
						return nil, errors.Errorf("creator must have format \"users/{email}\", got %q", creatorStr)
					}
					creatorEmail := strings.TrimPrefix(creatorStr, "users/")
					return qb.Q().Space("access_grant.creator = ?", creatorEmail), nil
				case "status":
					statusStr, ok := value.(string)
					if !ok {
						return nil, errors.Errorf("status value must be a string")
					}
					return getAccessGrantStatusFilter(statusStr)
				case "query":
					queryStr, ok := value.(string)
					if !ok {
						return nil, errors.Errorf("query value must be a string")
					}
					// Trim the same whitespace set on both sides (boundary
					// only) so the run-time JIT match in preCheckAccess
					// survives invisible boundary differences — most
					// commonly a trailing \n that Monaco's getValue() emits
					// in the request drawer but that the editor's
					// getActiveStatement() doesn't.
					//
					// We deliberately do NOT collapse internal whitespace.
					// Doing so would let "SELECT * FROM t --\nWHERE x=1"
					// compare equal to "SELECT * FROM t -- WHERE x=1",
					// silently authorizing a query with the WHERE clause

View on GitHub (pinned to 1870550677)

Solutions

  1. Quote the status value in the filter: `status == "ACTIVE"`.
  2. Use the exact string constant accepted by getAccessGrantStatusFilter (e.g. STATE_ACTIVE / STATE_DISABLED per the proto enum names).
  3. Fix the client/SDK that is serializing the enum as a number into the filter string.
  4. If the value type is legitimately variable, add an explicit string cast or a numeric branch in the compiler before the type assertion.

Example fix

// before
filter = "status == 1"
// after
filter = "status == \"ACTIVE\""
Defensive patterns

Strategy: validation

Validate before calling

// Before sending the filter, ensure the status literal is a quoted string:
if !strings.Contains(filter, `status == "`) && strings.Contains(filter, "status ==") {
    return fmt.Errorf("filter %q: status literal must be a quoted string", filter)
}

Type guard

func isStringLiteral(v any) (string, bool) {
    s, ok := v.(string)
    return s, ok
}

Try / catch

qq, err := store.ListAccessGrants(ctx, filter)
if err != nil {
    if strings.Contains(err.Error(), "status value must be a string") {
        // fall back to a corrected/quoted filter or surface a 400 to the client
    }
    return err
}

Prevention

When it happens

Trigger: Calling ListAccessGrants (or SearchAccessGrants) with a filter like `status == 1`, `status == true`, or `status in [1]`-style comparisons where the compared value is a number, bool, list, or bytes literal instead of a string.

Common situations: Hand-written CEL filters with unquoted enum values (`status == ACTIVE` resolves to an identifier, or `status == 0`), SDK clients passing numeric status codes from older API versions, and code generators that emit the wire enum number rather than the string state name.

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/af665ca48e418cf2. Report an issue: GitHub.