{"record":{"id":"096cb0d8cc404cbf","repo":"go-kit/kit","slug":"casbinpolicy-is-required-in-context","errorCode":null,"errorMessage":"CasbinPolicy is required in context","messagePattern":"CasbinPolicy is required in context","errorType":"exception","errorClass":"ErrPolicyContextMissing","httpStatus":500,"severity":"error","filePath":"auth/casbin/middleware.go","lineNumber":36,"sourceCode":"\n\t// CasbinPolicyContextKey holds the key to store the access control policy\n\t// in context, it can be a path to policy file or an implementation of\n\t// casbin/persist Adapter interface.\n\tCasbinPolicyContextKey contextKey = \"CasbinPolicy\"\n\n\t// CasbinEnforcerContextKey holds the key to retrieve the active casbin\n\t// Enforcer.\n\tCasbinEnforcerContextKey contextKey = \"CasbinEnforcer\"\n)\n\nvar (\n\t// ErrModelContextMissing denotes a casbin model was not passed into\n\t// the parsing of middleware's context.\n\tErrModelContextMissing = errors.New(\"CasbinModel is required in context\")\n\n\t// ErrPolicyContextMissing denotes a casbin policy was not passed into\n\t// the parsing of middleware's context.\n\tErrPolicyContextMissing = errors.New(\"CasbinPolicy is required in context\")\n\n\t// ErrUnauthorized denotes the subject is not authorized to do the action\n\t// intended on the given object, based on the context model and policy.\n\tErrUnauthorized = errors.New(\"Unauthorized Access\")\n)\n\n// NewEnforcer checks whether the subject is authorized to do the specified\n// action on the given object. If a valid access control model and policy\n// is given, then the generated casbin Enforcer is stored in the context\n// with CasbinEnforcer as the key.\nfunc NewEnforcer(\n\tsubject string, object interface{}, action string,\n) endpoint.Middleware {\n\treturn func(next endpoint.Endpoint) endpoint.Endpoint {\n\t\treturn func(ctx context.Context, request interface{}) (response interface{}, err error) {\n\t\t\tcasbinModel := ctx.Value(CasbinModelContextKey)\n\t\t\tcasbinPolicy := ctx.Value(CasbinPolicyContextKey)\n\t\t\tenforcer, err := stdcasbin.NewEnforcer(casbinModel, casbinPolicy)","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/go-kit/kit/blob/78fbbceece7bbcf073bee814a7772f4397ea756c/auth/casbin/middleware.go#L18-L54","documentation":"Sentinel error from go-kit's Casbin authorization middleware. It means the access-control policy was not present in the request context under CasbinPolicyContextKey when casbin.NewEnforcer(...) ran. The policy is either a path to a policy .csv file or an implementation of the casbin/persist Adapter interface; without it the Enforcer has no rules to evaluate and construction fails (older revisions map the nil check to this exact sentinel).","triggerScenarios":"Storing only the model in context but not the policy (context.WithValue with CasbinPolicyContextKey missing); passing a policy path that is empty; using a custom persist.Adapter but forgetting to put it in context; enforcer middleware ordered before the injection middleware so ctx.Value(CasbinPolicyContextKey) returns nil.","commonSituations":"Copying an example that only sets CasbinModelContextKey; switching from file-based policy to an adapter (e.g. SQL) and forgetting the context key still must be populated; renaming the policy file so the stored path points nowhere; test harnesses that build contexts by hand and skip the policy.","solutions":["Set the policy alongside the model: context.WithValue(ctx, casbin.CasbinPolicyContextKey, \"rbac_policy.csv\") or your persist.Adapter instance","Verify both keys are set in the same middleware/RequestFunc and that it wraps the casbin middleware","Confirm the policy file path is correct and readable at runtime (absolute path or correct working dir)","If policy lives in a database, register your casbin adapter under the same context key"],"exampleFix":"// before: only the model is injected\nctx = context.WithValue(ctx, casbin.CasbinModelContextKey, \"rbac_model.conf\")\n// -> \"CasbinPolicy is required in context\"\n\n// after: inject BOTH model and policy\nctx = context.WithValue(ctx, casbin.CasbinModelContextKey, \"rbac_model.conf\")\nctx = context.WithValue(ctx, casbin.CasbinPolicyContextKey, \"rbac_policy.csv\")\n// or with a DB-backed policy:\n// ctx = context.WithValue(ctx, casbin.CasbinPolicyContextKey, mySQLAdapter)","handlingStrategy":"validation","validationCode":"func casbinInputsPresent(ctx context.Context) error {\n\tif ctx.Value(casbin.CasbinModelContextKey) == nil {\n\t\treturn casbin.ErrModelContextMissing\n\t}\n\tif ctx.Value(casbin.CasbinPolicyContextKey) == nil {\n\t\treturn casbin.ErrPolicyContextMissing\n\t}\n\treturn nil\n}","typeGuard":"func hasCasbinPolicy(ctx context.Context) bool {\n\treturn ctx.Value(casbin.CasbinPolicyContextKey) != nil\n}","tryCatchPattern":"resp, err := ep(ctx, req)\nif err != nil {\n\tswitch {\n\tcase errors.Is(err, casbin.ErrPolicyContextMissing):\n\t\t// configuration bug: 500 + alert\n\tcase errors.Is(err, casbin.ErrUnauthorized):\n\t\t// 403\n\tdefault:\n\t\t// 500\n\t}\n}","preventionTips":["Set model and policy in the same middleware function — one without the other is always a bug","If the policy is a file path, stat it at startup so a missing file fails fast at boot, not per request","Cover the full middleware chain in an integration test that asserts context keys are populated"],"tags":["go","go-kit","casbin","authorization","context","policy"],"backgroundTag":null,"analyzedSha":"78fbbceece7bbcf073bee814a7772f4397ea756c","analyzedAt":"2026-08-15T22:31:35.570Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}