grpc/grpc-go · error
"headers" %d: "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 matcher has a key but no "values" array (or an empty one). A header permission rule needs at least one value to match against, so a values-less entry is rejected. The %d is the offending entry index.
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 03255a9237)
Solutions
- Add a non-empty "values" array to every header matcher entry.
- If you want presence-based matching, list the expected value(s) or reconsider the rule structure.
- Validate the policy JSON with a schema requiring values when key is present.
- Inspect the entry at the reported index and fill in its values.
Example fix
// before
{"headers":[{"key":"x-role"}]}
// after
{"headers":[{"key":"x-role","values":["admin"]}]} Defensive patterns
Strategy: validation
Validate before calling
for i, h := range policyHeaders {
if len(h.Values) == 0 {
return fmt.Errorf("headers[%d] missing values", i)
}
} Try / catch
interceptor, err := authz.NewStatic(policyJSON)
if err != nil {
return fmt.Errorf("invalid authz policy: %w", err)
} Prevention
- Always include a non-empty values array in header matchers.
- Schema-validate the policy before deploy.
- Review the header entry at the reported index when the error appears.
When it happens
Trigger: A policy "headers" entry like {"key":"x-foo"} with no "values" field, or "values":[] with zero elements.
Common situations: Omitting values thinking the key alone matches presence; copy-paste truncation; policy generator dropping empty arrays.
Related errors
- "headers" %d: "key" is not present
- "headers" %d: unsupported "key" %s
- authz: authorization policy file path is empty
- authz: requires refresh interval(%v) greater than 0s
- policyFile(%s) read failed: %v
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/580102bfa45840b1.
Report an issue: GitHub.