go-kit/kit · error · ErrPolicyContextMissing

CasbinPolicy is required in context

Error message

CasbinPolicy is required in context

What it means

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).

Source

Thrown at auth/casbin/middleware.go:36

	// CasbinPolicyContextKey holds the key to store the access control policy
	// in context, it can be a path to policy file or an implementation of
	// casbin/persist Adapter interface.
	CasbinPolicyContextKey contextKey = "CasbinPolicy"

	// CasbinEnforcerContextKey holds the key to retrieve the active casbin
	// Enforcer.
	CasbinEnforcerContextKey contextKey = "CasbinEnforcer"
)

var (
	// ErrModelContextMissing denotes a casbin model was not passed into
	// the parsing of middleware's context.
	ErrModelContextMissing = errors.New("CasbinModel is required in context")

	// ErrPolicyContextMissing denotes a casbin policy was not passed into
	// the parsing of middleware's context.
	ErrPolicyContextMissing = errors.New("CasbinPolicy is required in context")

	// ErrUnauthorized denotes the subject is not authorized to do the action
	// intended on the given object, based on the context model and policy.
	ErrUnauthorized = errors.New("Unauthorized Access")
)

// NewEnforcer checks whether the subject is authorized to do the specified
// action on the given object. If a valid access control model and policy
// is given, then the generated casbin Enforcer is stored in the context
// with CasbinEnforcer as the key.
func NewEnforcer(
	subject string, object interface{}, action string,
) endpoint.Middleware {
	return func(next endpoint.Endpoint) endpoint.Endpoint {
		return func(ctx context.Context, request interface{}) (response interface{}, err error) {
			casbinModel := ctx.Value(CasbinModelContextKey)
			casbinPolicy := ctx.Value(CasbinPolicyContextKey)
			enforcer, err := stdcasbin.NewEnforcer(casbinModel, casbinPolicy)

View on GitHub (pinned to 78fbbceece)

Solutions

  1. Set the policy alongside the model: context.WithValue(ctx, casbin.CasbinPolicyContextKey, "rbac_policy.csv") or your persist.Adapter instance
  2. Verify both keys are set in the same middleware/RequestFunc and that it wraps the casbin middleware
  3. Confirm the policy file path is correct and readable at runtime (absolute path or correct working dir)
  4. If policy lives in a database, register your casbin adapter under the same context key

Example fix

// before: only the model is injected
ctx = context.WithValue(ctx, casbin.CasbinModelContextKey, "rbac_model.conf")
// -> "CasbinPolicy is required in context"

// after: inject BOTH model and policy
ctx = context.WithValue(ctx, casbin.CasbinModelContextKey, "rbac_model.conf")
ctx = context.WithValue(ctx, casbin.CasbinPolicyContextKey, "rbac_policy.csv")
// or with a DB-backed policy:
// ctx = context.WithValue(ctx, casbin.CasbinPolicyContextKey, mySQLAdapter)
Defensive patterns

Strategy: validation

Validate before calling

func casbinInputsPresent(ctx context.Context) error {
	if ctx.Value(casbin.CasbinModelContextKey) == nil {
		return casbin.ErrModelContextMissing
	}
	if ctx.Value(casbin.CasbinPolicyContextKey) == nil {
		return casbin.ErrPolicyContextMissing
	}
	return nil
}

Type guard

func hasCasbinPolicy(ctx context.Context) bool {
	return ctx.Value(casbin.CasbinPolicyContextKey) != nil
}

Try / catch

resp, err := ep(ctx, req)
if err != nil {
	switch {
	case errors.Is(err, casbin.ErrPolicyContextMissing):
		// configuration bug: 500 + alert
	case errors.Is(err, casbin.ErrUnauthorized):
		// 403
	default:
		// 500
	}
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of go-kit/kit@78fbbceece (2026-08-15). Data as JSON: /api/errors/096cb0d8cc404cbf. Report an issue: GitHub.