{"record":{"id":"86cb7c5d3c535106","repo":"instructure/canvas-lms","slug":"root-account-id-required","errorCode":null,"errorMessage":"root_account_id required","messagePattern":"root_account_id required","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"app/models/role.rb","lineNumber":128,"sourceCode":"  include Workflow\n\n  workflow do\n    state :active do\n      event :deactivate, transitions_to: :inactive\n    end\n    state :inactive do\n      event :activate, transitions_to: :active\n    end\n    state :built_in # for previously built-in roles\n    state :deleted\n  end\n\n  def belongs_to_account?\n    !built_in? && !deleted?\n  end\n\n  def self.built_in_roles(root_account_id:)\n    raise \"root_account_id required\" unless root_account_id\n\n    # giving up on in-process built-in role caching because it's probably not really worth it anymore\n    RequestCache.cache(\"built_in_roles\", root_account_id) do\n      local_id, shard = Shard.local_id_for(root_account_id)\n      (shard || Shard.current).activate do\n        Role.where(workflow_state: \"built_in\", root_account_id: local_id).order(:id).to_a\n      end\n    end\n  end\n\n  def self.built_in_course_roles(root_account_id:)\n    built_in_roles(root_account_id:).select(&:course_role?)\n  end\n\n  def self.visible_built_in_roles(root_account_id:)\n    built_in_roles(root_account_id:).select(&:visible?)\n  end\n","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/role.rb#L110-L146","documentation":"Role.built_in_roles is a class-level lookup of a root account's built-in roles, keyed by root_account_id for sharded caching. Canvas raises this RuntimeError when called without a root_account_id, since the cache key and shard routing depend on it.","triggerScenarios":"Calling Role.built_in_roles without the root_account_id keyword argument, or passing nil (e.g. account&.root_account_id nil for a misconfigured/bad account record).","commonSituations":"Calling from code paths where the account may be a non-root account without resolving root_account first; seeds or scripts constructing roles without an account; nil propagation from an unsaved or deleted account.","solutions":["Pass an explicit root_account_id: Role.built_in_roles(root_account_id: account.root_account_id)","Resolve the root account first (account.root_account_id || account.id) before the call","Guard the call site: skip or raise a clearer error when root_account_id is blank"],"exampleFix":"// before\nroles = Role.built_in_roles\n// after\nroles = Role.built_in_roles(root_account_id: account.root_account_id || account.id)","handlingStrategy":"validation","validationCode":"raise ArgumentError, \"root_account_id required\" if root_account_id.blank?","typeGuard":"def has_root_account?(account) = account&.root_account_id.present? || (account&.is_a?(Account) && !account.new_record?)","tryCatchPattern":"begin\n  roles = Role.built_in_roles(root_account_id: ra_id)\nrescue RuntimeError => e\n  raise unless e.message == \"root_account_id required\"\n  roles = []\nend","preventionTips":["Always resolve account.root_account_id before role lookups","Guard against nil accounts in seed/import scripts","Prefer keyword-arg call sites with explicit values, not interpolated nils"],"tags":["ruby","rails","roles","multi-tenancy","missing-argument"],"backgroundTag":"missing-required-argument","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"}