{"record":{"id":"82f845c7de799aaf","repo":"padrino/padrino-framework","slug":"role-role-must-be-present-and-must-be-a-symbol","errorCode":null,"errorMessage":"Role #{role} must be present and must be a symbol!","messagePattern":"Role #(.+?) must be present and must be a symbol!","errorType":"exception","errorClass":"Padrino::Admin::AccessControlError","httpStatus":null,"severity":"error","filePath":"padrino-admin/lib/padrino-admin/access_control.rb","lineNumber":47,"sourceCode":"\n          app.send(:access_control=, Padrino::Admin::AccessControl::Base.new)\n        end\n        alias included registered\n      end\n\n      ##\n      # This base access control class where roles are defined as are authorizations.\n      #\n      class Base\n        def initialize\n          @roles, @authorizations, @project_modules = [], [], []\n        end\n\n        ##\n        # We map project modules for a given role or roles.\n        #\n        def roles_for(*roles, &block)\n          raise Padrino::Admin::AccessControlError, \"Role #{role} must be present and must be a symbol!\" if roles.any? { |r| !r.is_a?(Symbol) } || roles.empty?\n          raise Padrino::Admin::AccessControlError, \"You can't merge :any with other roles\" if roles.size > 1 && roles.any? { |r| r == :any }\n\n          @roles += roles\n          @authorizations << Authorization.new(*roles, &block)\n        end\n\n        ##\n        # Return an array of roles.\n        #\n        def roles\n          @roles.uniq.reject { |r| r == :any }\n        end\n\n        ##\n        # Return an array of project_modules.\n        #\n        def project_modules(account)\n          role = account.role.to_sym rescue :any","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/padrino/padrino-framework/blob/167044f3d56b2bce12f943eb826fdb0b0ea94375/padrino-admin/lib/padrino-admin/access_control.rb#L29-L65","documentation":"Padrino::Admin::AccessControl::Base#roles_for maps project modules to roles and validates its arguments: at least one role must be supplied and every role must be a Symbol (:admin, not 'admin'). Note a latent bug in this source: the message interpolates an undefined variable `role` (the parameter is `roles`), so when this branch trips you may actually see a NameError about `role` instead of this text — the root cause is still an empty or non-Symbol role list.","triggerScenarios":"Calling access_control.roles_for with no arguments (roles.empty?); passing strings like roles_for('admin'); passing role values read from ENV, YAML, params or a database that arrive as Strings; splatting a dynamic array whose entries are not Symbols.","commonSituations":"Editing the access_control block in admin/app.rb and quoting the role; building role lists from config files or a roles table; copying examples where the role came from user input (always a String).","solutions":["Pass at least one role and use Symbols: access_control.roles_for(:admin) do |role| ... end","When roles come from config or the database, convert first: roles_for(*roles.map(&:to_sym))","If you instead saw a NameError mentioning `role`, you hit the interpolation bug at access_control.rb:47 — fix the call as above, or patch the message to interpolate roles.inspect"],"exampleFix":"# before\naccess_control.roles_for('admin') do |role| ... end\n\n# after\naccess_control.roles_for(:admin) do |role| ... end\n\n# dynamic roles\naccess_control.roles_for(*config_roles.map(&:to_sym)) do |role| ... end","handlingStrategy":"validation","validationCode":"roles = Array(config_roles)\nif roles.empty? || roles.any? { |r| !r.is_a?(Symbol) }\n  raise ArgumentError, \"roles must be non-empty Symbols: #{roles.inspect}\"\nend\naccess_control.roles_for(*roles) { |role| ... }","typeGuard":"def valid_roles?(*roles) = !roles.empty? && roles.all? { |r| r.is_a?(Symbol) }","tryCatchPattern":"begin\n  access_control.roles_for(*roles, &block)\nrescue Padrino::Admin::AccessControlError, NameError\n  warn \"invalid access_control roles: #{roles.inspect}\" # boot-time config bug — fix and re-run\n  raise\nend","preventionTips":["Write roles as bare Symbols in app.rb; never quote them","Convert external role data with .map(&:to_sym) before it reaches roles_for","Treat AccessControlError (or a NameError on `role`) at boot as a config typo, not a runtime condition to rescue"],"tags":["padrino-admin","access-control","ruby","roles","configuration"],"backgroundTag":"invalid-configuration-value","analyzedSha":"167044f3d56b2bce12f943eb826fdb0b0ea94375","analyzedAt":"2026-08-23T12:41:41.049Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}