{"record":{"id":"1abaa951fa8809fd","repo":"gofr-dev/gofr","slug":"endpoint-d-w-s","errorCode":null,"errorMessage":"endpoint[%d]: %w: %s","messagePattern":"endpoint\\[(.+?)\\]: %w: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/rbac/config.go","lineNumber":185,"sourceCode":"\tif err := config.validate(); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid RBAC config: %w\", err)\n\t}\n\n\t// Process unified config to build internal maps\n\tif err := config.processUnifiedConfig(); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to process unified config: %w\", err)\n\t}\n\n\treturn &config, nil\n}\n\n// validate validates the RBAC configuration.\nfunc (c *Config) validate() error {\n\t// Validate endpoints: non-public endpoints must have RequiredPermissions\n\t// Also validate that paths use mux patterns only (no wildcards or old regex)\n\tfor i, endpoint := range c.Endpoints {\n\t\tif !endpoint.Public && len(endpoint.RequiredPermissions) == 0 {\n\t\t\treturn fmt.Errorf(\"endpoint[%d]: %w: %s\", i, ErrEndpointMissingPermissions, endpoint.Path)\n\t\t}\n\n\t\t// Validate path pattern\n\t\tif err := c.validateEndpointPath(endpoint.Path, i); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// validateEndpointPath validates that an endpoint path uses mux patterns only.\n// Rejects wildcard patterns (/*) and old regex patterns (^...$).\nfunc (c *Config) validateEndpointPath(path string, index int) error {\n\tif path == \"\" {\n\t\treturn nil // Empty path is handled elsewhere\n\t}\n","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/rbac/config.go#L167-L203","documentation":"Config.validate found a non-public endpoint (index %d) whose RequiredPermissions list is empty, wrapped with ErrEndpointMissingPermissions. RBAC refuses to load because a protected endpoint without required permissions would silently allow everyone.","triggerScenarios":"An Endpoints entry with Public=false and len(RequiredPermissions)==0 passed to EnableRBAC/LoadPermissions.","commonSituations":"Adding a protected route and forgetting requiredPermissions; an empty array after filtering/templating removed values; migrating a public endpoint to protected without adding permissions.","solutions":["Add at least one required permission to the endpoint named in the error.","If the endpoint should be public, explicitly set Public=true.","If permissions are injected via templates, verify the rendered config is non-empty."],"exampleFix":"// before\nrbac.Endpoint{Path: \"/api/users\", Methods: []string{\"GET\"}}\n// after\nrbac.Endpoint{Path: \"/api/users\", Methods: []string{\"GET\"}, RequiredPermissions: []string{\"users:read\"}}","handlingStrategy":"validation","validationCode":"for i, ep := range endpoints {\n    if !ep.Public && len(ep.RequiredPermissions) == 0 {\n        return fmt.Errorf(\"endpoint[%d] (%s): must set RequiredPermissions or Public=true\", i, ep.Path)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := prevalidateEndpoints(endpoints); err != nil { return err }\nif _, err := rbac.LoadPermissions(path, logger, metrics, tracer); err != nil {\n    var target error\n    if errors.Is(err, rbac.ErrEndpointMissingPermissions) || strings.Contains(err.Error(), \"endpoint[\") {\n        return fmt.Errorf(\"rbac config rejected: %w\", err)\n    }\n    return err\n}","preventionTips":["Make requiredPermissions a required field in your config schema for non-public endpoints.","Add a unit test asserting every non-public endpoint has permissions.","Review templating that could render permissions as an empty array.","Default new endpoints to explicit permission lists rather than empty."],"tags":["go","rbac","config","validation","permissions"],"backgroundTag":"missing-required-permission","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}