{"record":{"id":"2df46bd787353986","repo":"instructure/canvas-lms","slug":"discussion-checkpoints-feature-flag-must-be-enabled","errorCode":null,"errorMessage":"discussion_checkpoints feature flag must be enabled","messagePattern":"discussion_checkpoints feature flag must be enabled","errorType":"validation","errorClass":"Checkpoints::FlagDisabledError","httpStatus":null,"severity":"error","filePath":"app/services/checkpoints/discussion_checkpoint_common_service.rb","lineNumber":37,"sourceCode":"\nclass Checkpoints::DiscussionCheckpointCommonService < ApplicationService\n  def initialize(discussion_topic:, checkpoint_label:, dates:, points_possible: nil, replies_required: 1, saved_by: nil, updating_user: nil)\n    super()\n    @discussion_topic = discussion_topic\n    @assignment = discussion_topic.assignment\n    @checkpoint_label = checkpoint_label\n    @dates = dates\n    @points_possible = points_possible\n    @replies_required = replies_required\n    @saved_by = saved_by\n    @updating_user = updating_user\n  end\n\n  private\n\n  def validate_flag_enabled\n    unless @discussion_topic.context.discussion_checkpoints_enabled?\n      raise Checkpoints::FlagDisabledError, \"discussion_checkpoints feature flag must be enabled\"\n    end\n  end\n\n  def validate_dates\n    valid_date_types = %w[everyone override].freeze\n\n    @dates.each do |date|\n      if date[:type].blank?\n        raise Checkpoints::DateTypeRequiredError, \"each date must have a type specified ('everyone' or 'override')\"\n      end\n      unless valid_date_types.include?(date[:type])\n        raise Checkpoints::InvalidDateTypeError, \"invalid date type: #{date[:type]}\"\n      end\n    end\n  end\n\n  def attributes_to_inherit_from_parent\n    # TODO: handle peer reviews","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/checkpoints/discussion_checkpoint_common_service.rb#L19-L55","documentation":"Checkpoints::DiscussionCheckpointCommonService#validate_flag_enabled checks that the discussion topic's root context has the discussion_checkpoints feature enabled via discussion_checkpoints_enabled?. If not, it raises FlagDisabledError. All discussion checkpoint create/update/delete services run this guard before doing any work, since checkpoints are gated behind the feature flag.","triggerScenarios":"Any create/update/delete call on Checkpoints discussion services (e.g. DiscussionCheckpointCreatorService#call) for a course/account where the :discussion_checkpoints feature flag is off; calling with a discussion_topic in a context (e.g. a user or group context) that doesn't support the flag.","commonSituations":"Testing checkpoint code locally without enabling the flag; staging/production environments where the flag hasn't been enabled for the account; requests hitting a course in an account that opted out; specs that forget to stub Account.site_admin.feature_enabled?(:discussion_checkpoints).","solutions":["Enable the discussion_checkpoints feature flag for the account (or site admin) via Account settings UI or rails console: account.enable_feature!(:discussion_checkpoints).","In tests, stub the flag before calling the service.","Confirm the discussion topic belongs to a Course context, not a group/user context without the flag."],"exampleFix":"// before (spec)\ncreator.call(discussion_topic:, dates: ...)\n// after\nallow_any_instance_of(Account).to receive(:discussion_checkpoints_enabled?).and_return(true)\ncreator.call(discussion_topic:, dates: ...)","handlingStrategy":"try-catch","validationCode":"unless discussion_topic.context.discussion_checkpoints_enabled?\n  raise Checkpoints::FlagDisabledError\nend","typeGuard":null,"tryCatchPattern":"begin\n  service.call(...)\nrescue Checkpoints::FlagDisabledError\n  render json: { error: 'discussion_checkpoints is not enabled for this context' }, status: :forbidden\nend","preventionTips":["Enable discussion_checkpoints on the account (or in specs) before exercising checkpoint services","Gate UI/API routes for checkpoints on the same flag check so calls never reach the service","Remember the check is per discussion_topic.context — group/user contexts behave differently"],"tags":["ruby","canvas","feature-flag","checkpoints"],"backgroundTag":"feature-not-enabled","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"}