{"record":{"id":"580102bfa45840b1","repo":"grpc/grpc-go","slug":"headers-d-values-is-not-present","errorCode":null,"errorMessage":"\"headers\" %d: \"values\" is not present","messagePattern":"\"headers\" (.+?): \"values\" is not present","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"authz/rbac_translator.go","lineNumber":240,"sourceCode":"\t\"upgrade\":             true,\n}\n\nfunc unsupportedHeader(key string) bool {\n\treturn key[0] == ':' || strings.HasPrefix(key, \"grpc-\") || unsupportedHeaders[key]\n}\n\nfunc parseHeaders(headers []header) ([]*v3rbacpb.Permission, error) {\n\ths := make([]*v3rbacpb.Permission, 0, len(headers))\n\tfor i, header := range headers {\n\t\tif header.Key == \"\" {\n\t\t\treturn nil, fmt.Errorf(`\"headers\" %d: \"key\" is not present`, i)\n\t\t}\n\t\theader.Key = strings.ToLower(header.Key)\n\t\tif unsupportedHeader(header.Key) {\n\t\t\treturn nil, fmt.Errorf(`\"headers\" %d: unsupported \"key\" %s`, i, header.Key)\n\t\t}\n\t\tif len(header.Values) == 0 {\n\t\t\treturn nil, fmt.Errorf(`\"headers\" %d: \"values\" is not present`, i)\n\t\t}\n\t\tvalues := parseHeaderValues(header.Key, header.Values)\n\t\ths = append(hs, permissionOr(values))\n\t}\n\treturn hs, nil\n}\n\nfunc parseRequest(request request) (*v3rbacpb.Permission, error) {\n\tvar and []*v3rbacpb.Permission\n\tif len(request.Paths) > 0 {\n\t\tand = append(and, permissionOr(parsePaths(request.Paths)))\n\t}\n\tif len(request.Headers) > 0 {\n\t\theaders, err := parseHeaders(request.Headers)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tand = append(and, permissionAnd(headers))","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/authz/rbac_translator.go#L222-L258","documentation":"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.","triggerScenarios":"A policy rule request.headers[] entry with \"key\" but no \"values\", or \"values\": []; e.g. {\"key\":\"authorization\"}.","commonSituations":"Authoring a header matcher and forgetting the values; a templating step that strips empty arrays; refactoring that moved values elsewhere.","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."],"exampleFix":"// before\n\"headers\": [ { \"key\": \"authorization\" } ]\n\n// after\n\"headers\": [ { \"key\": \"authorization\", \"values\": [\"*\"] } ]","handlingStrategy":"validation","validationCode":"func validHeader(h struct{ Key string; Values []string }) error {\n    if h.Key == \"\" || len(h.Values) == 0 {\n        return errors.New(\"header requires key and at least one value\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"interceptor, err := authz.NewStatic(policyJSON)\nif err != nil {\n    if strings.Contains(err.Error(), `\"values\" is not present`) {\n        // add values to the flagged header entry and reload\n    }\n}","preventionTips":["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."],"tags":["grpc","authz","rbac","policy","config","go"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}