{"record":{"id":"39cded7d95b2a55a","repo":"instructure/canvas-lms","slug":"course-exceeds-accessibility-scan-limit","errorCode":null,"errorMessage":"Course exceeds accessibility scan limit","messagePattern":"Course exceeds accessibility scan limit","errorType":"exception","errorClass":"ScanLimitExceededError","httpStatus":null,"severity":"warning","filePath":"app/services/accessibility/course_scan_service.rb","lineNumber":36,"sourceCode":"# with this program. If not, see <http://www.gnu.org/licenses/>.\n\nclass Accessibility::CourseScanService < ApplicationService\n  include Accessibility::Concerns::CourseStatisticsQueueable\n\n  SCAN_TAG = \"course_accessibility_scan\"\n\n  class ScanLimitExceededError < StandardError; end\n\n  def self.last_accessibility_course_scan(course)\n    Progress.where(tag: SCAN_TAG, context: course).last\n  end\n\n  def self.queue_course_scan(course)\n    progress = Progress.where(tag: SCAN_TAG, context_type: \"Course\", context_id: course.id).last\n    return progress if progress&.pending?\n\n    if course.exceeds_accessibility_scan_limit?\n      raise ScanLimitExceededError, \"Course exceeds accessibility scan limit\"\n    end\n\n    progress = Progress.create!(tag: SCAN_TAG, context: course)\n\n    n_strand = [SCAN_TAG, course.global_id]\n    singleton = \"#{SCAN_TAG}_#{course.global_id}\"\n    progress.process_job(self, :scan, { n_strand:, singleton: })\n    progress\n  end\n\n  def self.scan(progress)\n    service = new(course: progress.context)\n    service.scan_course\n    progress.set_results({})\n    progress.complete!\n    service.queue_course_statistics(progress.context)\n  rescue => e\n    progress.fail!","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/accessibility/course_scan_service.rb#L18-L54","documentation":"Accessibility::CourseScanService.queue_course_scan refuses to enqueue a new accessibility scan when course.exceeds_accessibility_scan_limit? is true, raising ScanLimitExceededError 'Course exceeds accessibility scan limit'. Very large courses are blocked from scanning to protect job throughput and prevent oversized scans.","triggerScenarios":"Request an accessibility course scan (via API or UI) on a Course whose content size/count (e.g. number of pages/assignments/files, per exceeds_accessibility_scan_limit?) is above the configured scan limit, and no pending Progress with tag SCAN_TAG already exists for it.","commonSituations":"Very large courses (thousands of pages/items) triggering scans; instances with a low accessibility scan limit setting; scripts batch-queuing scans across all courses hitting the limit on the biggest ones.","solutions":["Raise the accessibility scan limit setting (account/root-account setting governing exceeds_accessibility_scan_limit?) if scanning large courses is intended.","Skip or batch the scan for oversized courses; scan a subset of content instead.","Check course.exceeds_accessibility_scan_limit? before queueing and handle the refusal gracefully in the caller.","Reduce course content size or archive unused content, then retry the scan."],"exampleFix":"// before\nAccessibility::CourseScanService.queue_course_scan(course) # raises for huge courses\n\n// after\nif course.exceeds_accessibility_scan_limit?\n  Rails.logger.info(\"Skipping accessibility scan for course #{course.id}: over scan limit\")\nelse\n  Accessibility::CourseScanService.queue_course_scan(course)\nend","handlingStrategy":"validation","validationCode":"if course.exceeds_accessibility_scan_limit?\n  return render json: { error: 'Course exceeds accessibility scan limit' }, status: :unprocessable_entity\nend","typeGuard":"def scan_eligible?(course)\n  !course.exceeds_accessibility_scan_limit?\nend","tryCatchPattern":"begin\n  Accessibility::CourseScanService.queue_course_scan(course)\nrescue Accessibility::ScanLimitExceededError\n  flash[:warning] = 'This course is too large for an accessibility scan.'\nend","preventionTips":["Check exceeds_accessibility_scan_limit? before queueing scans, especially in batch jobs.","Raise the scan limit setting if large-course scans are a legitimate need.","Scan large courses in content subsets instead of a whole-course scan."],"tags":["accessibility","scan-limit","background-jobs","guard-rail"],"backgroundTag":"file-size-limit-exceeded","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"}