{"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/03255a9237b6eb32710f6bc4f2de9a675b99fe36/authz/rbac_translator.go#L349-L385","documentation":"Raised by translatePolicy when the top-level policy JSON cannot be decoded. The decoder uses DisallowUnknownFields, so this fires both on malformed JSON AND on any field name not in the authorizationPolicy schema. The wrapped %v is the encoding/json error identifying the offending token/position.","triggerScenarios":"Calling the authz SDK with a policy string that is invalid JSON, has a trailing comma, or contains an unknown top-level field (e.g. a typo like \"allow_rule\" instead of \"allow_rules\", or a field from a different schema version).","commonSituations":"YAML-to-JSON conversion producing trailing commas or comments; copy-pasting a field name from an Envoy RBAC config that doesn't exist in the gRPC SDK schema; using a field from a newer authz version on an older grpc-go; mismatched casing (AllowRules vs allow_rules).","solutions":["Run the policy string through `jq .` to confirm it is valid JSON.","Compare top-level keys against the SDK's authorizationPolicy struct (Name, AllowRules, DenyRules, AuditLoggingOptions) — DisallowUnknownFields rejects anything else.","Upgrade or align grpc-go and the authz SDK versions so the schema matches your policy.","Wrap NewStaticInterceptors in a test that surfaces this error before runtime."],"exampleFix":"// before (unknown field + trailing comma):\n{ \"name\": \"p\", \"allow_rule\": [...] }   // 'allow_rule' unknown; trailing comma\n\n// after:\n{ \"name\": \"p\", \"allow_rules\": [ { \"name\": \"a\", \"request\": { \"paths\": [\"/x\"] } } ] }","handlingStrategy":"validation","validationCode":"// Strict decode mirroring translatePolicy's DisallowUnknownFields + JSON\n// validity, surfacing the exact offending token before the SDK rejects it.\nfunc validatePolicyJSON(policyStr string) error {\n    type authzPolicy struct {\n        Name               string          `json:\"name\"`\n        AllowRules         json.RawMessage `json:\"allow_rules\"`\n        DenyRules          json.RawMessage `json:\"deny_rules\"`\n        AuditLoggingOptions json.RawMessage `json:\"audit_logging_options\"`\n    }\n    d := json.NewDecoder(strings.NewReader(policyStr))\n    d.DisallowUnknownFields()\n    var p authzPolicy\n    if err := d.Decode(&p); err != nil {\n        return fmt.Errorf(\"failed to unmarshal policy: %v\", err)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run `jq .` on the policy before deploy.","Mirror DisallowUnknownFields in your own pre-flight decoder.","Keep field names lower_snake_case per the SDK schema.","Version-pin the SDK and align policy fields accordingly."],"tags":["authz","rbac","authorization-policy","json","config"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}