{"record":{"id":"728f0d77b594ab07","repo":"instructure/canvas-lms","slug":"must-be-a-siteadmin-user","errorCode":null,"errorMessage":"Must be a siteadmin user!","messagePattern":"Must be a siteadmin user!","errorType":"exception","errorClass":"NonSiteAdminError","httpStatus":null,"severity":"error","filePath":"app/services/site_admin_reporting_service.rb","lineNumber":57,"sourceCode":"  MAX_BACKTRACE_LINES = 1_000\n\n  attr_reader :user,\n              :source_name,\n              :custom_name,\n              :block\n\n  def initialize(user:, source_name:, custom_name: nil, &block)\n    super()\n    raise NoBlockError, \"Must provide a block!\" unless block_given?\n\n    @user = user\n    @source_name = source_name\n    @custom_name = custom_name\n    @block = block\n  end\n\n  def call\n    raise NonSiteAdminError, \"Must be a siteadmin user!\" unless Account.site_admin.grants_right?(user, :update)\n\n    begin\n      Tempfile.create do |file|\n        create_report(file)\n        file.rewind\n        create_attachment(file)\n      end\n    rescue => e\n      save_error_to_attachment(e)\n    end\n  end\n\n  private\n\n  # Creates a report. To be implemented in subclasses. The block attribute should\n  # be used to generate the content of the report.\n  # @param file [File] The file to write the report content to.\n  # Do not close this file, as it will be closed by the caller.","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/site_admin_reporting_service.rb#L39-L75","documentation":"NonSiteAdminError raised by SiteAdminReportingService#call when the invoking user does not have :update rights on the site-admin account. This service generates site-wide reports and is intentionally restricted to Canvas site administrators.","triggerScenarios":"Calling SiteAdminReportingService.new(user:, ...).call (or the wrapping job) with a user whose Account.site_admin grants do not include :update — i.e. any non-siteadmin user.","commonSituations":"Running a report rake task/console command as a regular admin instead of a siteadmin; misconfigured shard (site admin account on a different shard); automated jobs whose service user lost siteadmin rights; local dev without seed_admin data.","solutions":["Run the service as a user with siteadmin :update rights (e.g. the site admin user created by seeds)","Grant the user site-admin privileges: add them to the site admin account with admin/update rights","Verify you are on the default shard where Account.site_admin resolves to the correct account","Check the user/account setup in a dev environment (rails console: Account.site_admin.grants_right?(user, :update))"],"exampleFix":"// before\nSiteAdminReportingService.new(user: current_user, source_name: 'grades').call\n// after\nadmin = Account.site_admin.users.find_by(name: 'Site Admin')\nraise 'must run as siteadmin' unless Account.site_admin.grants_right?(admin, :update)\nSiteAdminReportingService.new(user: admin, source_name: 'grades').call","handlingStrategy":"validation","validationCode":"unless Account.site_admin.grants_right?(user, :update)\n  raise ArgumentError, 'SiteAdminReportingService requires a siteadmin user'\nend","typeGuard":"null","tryCatchPattern":"begin\n  SiteAdminReportingService.new(user:, source_name:).call\nrescue NonSiteAdminError\n  # reject the request with 403 or reroute to a privileged job\nend","preventionTips":["Only enqueue report jobs with a verified siteadmin user","Check grants_right?(user, :update) on Account.site_admin before invoking","Verify shard context so Account.site_admin resolves correctly","Audit service users' permissions after role changes"],"tags":["ruby","rails","permissions","siteadmin","reporting"],"backgroundTag":"permission-denied","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}