{"record":{"id":"8aede689e0727949","repo":"grpc/grpc-go","slug":"failed-to-unmarshal-policy-v","errorCode":null,"errorMessage":"failed to unmarshal policy: %v","messagePattern":"failed to unmarshal policy: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"authz/rbac_translator.go","lineNumber":367,"sourceCode":"\tcase v3rbacpb.RBAC_AuditLoggingOptions_ON_ALLOW:\n\t\treturn v3rbacpb.RBAC_AuditLoggingOptions_NONE\n\tcase v3rbacpb.RBAC_AuditLoggingOptions_ON_DENY_AND_ALLOW:\n\t\treturn v3rbacpb.RBAC_AuditLoggingOptions_ON_DENY\n\tdefault:\n\t\treturn v3rbacpb.RBAC_AuditLoggingOptions_NONE\n\t}\n}\n\n// translatePolicy translates SDK authorization policy in JSON format to two\n// Envoy RBAC polices (deny followed by allow policy) or only one Envoy RBAC\n// allow policy. Also returns the overall policy name. If the input policy\n// cannot be parsed or is invalid, an error will be returned.\nfunc translatePolicy(policyStr string) ([]*v3rbacpb.RBAC, string, error) {\n\tpolicy := &authorizationPolicy{}\n\td := json.NewDecoder(bytes.NewReader([]byte(policyStr)))\n\td.DisallowUnknownFields()\n\tif err := d.Decode(policy); err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"failed to unmarshal policy: %v\", err)\n\t}\n\tif policy.Name == \"\" {\n\t\treturn nil, \"\", fmt.Errorf(`\"name\" is not present`)\n\t}\n\tif len(policy.AllowRules) == 0 {\n\t\treturn nil, \"\", fmt.Errorf(`\"allow_rules\" is not present`)\n\t}\n\tallowLogger, denyLogger, err := policy.AuditLoggingOptions.toProtos()\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\trbacs := make([]*v3rbacpb.RBAC, 0, 2)\n\tif len(policy.DenyRules) > 0 {\n\t\tdenyPolicies, err := parseRules(policy.DenyRules, policy.Name)\n\t\tif err != nil {\n\t\t\treturn nil, \"\", fmt.Errorf(`\"deny_rules\" %v`, err)\n\t\t}\n\t\tdenyRBAC := &v3rbacpb.RBAC{","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/authz/rbac_translator.go#L349-L385","documentation":"Returned by translatePolicy (rbac_translator.go:367) when the authorization policy JSON cannot be decoded into authorizationPolicy. The decoder uses DisallowUnknownFields (line 365), so the error fires on malformed JSON, wrong types, or any unrecognized field name. The wrapped %v is the encoding/json error.","triggerScenarios":"Policy file/string that is not valid JSON, has a typo in a field name (e.g. \"allow_rule\" vs \"allow_rules\"), includes an unsupported field, or uses wrong value types.","commonSituations":"Hand-edited policy with trailing commas/comments (JSON, not JSON5); stale field names from an older policy version; extra fields that DisallowUnknownFields rejects.","solutions":["Validate the JSON with a JSON parser and check the wrapped error for line/field detail; remove or rename unknown fields.","Match the field names exactly: name, deny_rules, allow_rules, audit_logging_options (and within rules: name, source, request, paths, headers).","Strip comments/trailing commas; the policy is strict JSON.","Reload via the file watcher to keep the last good policy while you fix the file."],"exampleFix":"// before\n{ \"name\": \"p\", \"allow_rule\": [ {\"name\":\"r\"} ] } // typo + unknown field\n\n// after\n{ \"name\": \"p\", \"allow_rules\": [ {\"name\":\"r\",\"request\":{\"paths\":[\"/\"]}} ] }","handlingStrategy":"validation","validationCode":"// Validate JSON shape and unknown fields before loading.\nfunc validatePolicyJSON(s string) error {\n    p := &authorizationPolicy{}\n    d := json.NewDecoder(strings.NewReader(s))\n    d.DisallowUnknownFields()\n    return d.Decode(p)\n}","typeGuard":null,"tryCatchPattern":"interceptor, err := authz.NewStatic(policyJSON)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to unmarshal policy\") {\n        // json error; fix syntax/fields and reload (file watcher keeps prior policy)\n    }\n}","preventionTips":["Use strict JSON (no comments/trailing commas); validate before deploy.","Match exact field names; DisallowUnknownFields is on, so unknown keys are rejected.","Validate with the same decoder settings the library uses."],"tags":["grpc","authz","rbac","policy","json","config","go"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}