grpc/grpc-go · error
"headers" : "values" is not present
Error message
"headers" %d: "values" is not present
What it means
Returned by parseHeaders (rbac_translator.go:240) when a header entry has a key but its values array is empty or absent (len(header.Values) == 0). RBAC header matching requires at least one value to match against, so an empty values list is rejected at the given index.
Solutions
- Add at least one value to "values" for that header entry, e.g. ["Bearer ..."] or ["*"] for any value.
- Lint the policy JSON for header entries where values is missing or empty before deploy.
Example fix
// before
"headers": [ { "key": "authorization" } ]
// after
"headers": [ { "key": "authorization", "values": ["*"] } ] Defensive patterns
Strategy: validation
Validate before calling
func validHeader(h struct{ Key string; Values []string }) error {
if h.Key == "" || len(h.Values) == 0 {
return errors.New("header requires key and at least one value")
}
return nil
} Try / catch
interceptor, err := authz.NewStatic(policyJSON)
if err != nil {
if strings.Contains(err.Error(), `"values" is not present`) {
// add values to the flagged header entry and reload
}
} Prevention
- Always include a non-empty values array on header matchers.
- Use ["*"] to match any value of a required header.
- Lint policy JSON for header entries missing values.
When it happens
Trigger: A policy rule request.headers[] entry with "key" but no "values", or "values": []; e.g. {"key":"authorization"}.
Common situations: Authoring a header matcher and forgetting the values; a templating step that strips empty arrays; refactoring that moved values elsewhere.
Related errors
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/580102bfa45840b1.
Report an issue: GitHub.
Appendix: source
Thrown at authz/rbac_translator.go:240
"upgrade": true,
}
func unsupportedHeader(key string) bool {
return key[0] == ':' || strings.HasPrefix(key, "grpc-") || unsupportedHeaders[key]
}
func parseHeaders(headers []header) ([]*v3rbacpb.Permission, error) {
hs := make([]*v3rbacpb.Permission, 0, len(headers))
for i, header := range headers {
if header.Key == "" {
return nil, fmt.Errorf(`"headers" %d: "key" is not present`, i)
}
header.Key = strings.ToLower(header.Key)
if unsupportedHeader(header.Key) {
return nil, fmt.Errorf(`"headers" %d: unsupported "key" %s`, i, header.Key)
}
if len(header.Values) == 0 {
return nil, fmt.Errorf(`"headers" %d: "values" is not present`, i)
}
values := parseHeaderValues(header.Key, header.Values)
hs = append(hs, permissionOr(values))
}
return hs, nil
}
func parseRequest(request request) (*v3rbacpb.Permission, error) {
var and []*v3rbacpb.Permission
if len(request.Paths) > 0 {
and = append(and, permissionOr(parsePaths(request.Paths)))
}
if len(request.Headers) > 0 {
headers, err := parseHeaders(request.Headers)
if err != nil {
return nil, err
}
and = append(and, permissionAnd(headers))View on GitHub (pinned to 0c51461d27)