{"record":{"id":"57404f6d820aa398","repo":"instructure/canvas-lms","slug":"set-id-is-required-but-was-not-provided-group-override","errorCode":null,"errorMessage":"set_id is required, but was not provided","messagePattern":"set_id is required, but was not provided","errorType":"exception","errorClass":"Checkpoints::SetIdRequiredError","httpStatus":null,"severity":"error","filePath":"app/services/checkpoints/group_override_updater_service.rb","lineNumber":41,"sourceCode":"\n  def initialize(checkpoint:, override:)\n    super()\n    @checkpoint = checkpoint\n    @override = override\n  end\n\n  def call\n    is_differentiation_tag_override = differentiation_tag_override?(@override, @checkpoint)\n    if @checkpoint.effective_group_category_id.nil? && !is_differentiation_tag_override\n      raise Checkpoints::GroupAssignmentRequiredError, \"must be a group assignment in order to create group overrides\"\n    end\n\n    override = @checkpoint.assignment_overrides.find_by(id: @override[:id], set_type: AssignmentOverride::SET_TYPE_GROUP)\n    raise Checkpoints::OverrideNotFoundError unless override\n\n    group_id = @override.fetch(:set_id, nil) || override.set_id\n\n    raise Checkpoints::SetIdRequiredError, \"set_id is required, but was not provided\" if group_id.blank?\n\n    group = is_differentiation_tag_override ? get_differentiation_tag_from_override(@override, @checkpoint) : get_group_from_override(@override, @checkpoint)\n\n    current_group = override.set\n\n    update_override(override:, group:)\n\n    parent_override = @checkpoint.parent_assignment.active_assignment_overrides.find_by(set: current_group)\n    raise Checkpoints::OverrideNotFoundError unless parent_override\n\n    update_override(override: parent_override, group:, shell_override: true)\n\n    override\n  end\n\n  private\n\n  def update_override(override:, group:, shell_override: false)","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/checkpoints/group_override_updater_service.rb#L23-L59","documentation":"Checkpoints::SetIdRequiredError raised in GroupOverrideUpdaterService#call via get_group_from_override/get_differentiation_tag_from_override (the shared common module) when the override hash lacks :set_id. Unlike 514, this fires when the fetch(:set_id) call itself misses the key, i.e. the payload key is entirely absent.","triggerScenarios":"Updater's group_id fallback succeeded via override.set_id, but a downstream call re-fetches :set_id from the raw override hash with fetch(:set_id){raise}, and the original payload had no set_id key. Actually in flow, this triggers when the shared helpers are called with a hash missing :set_id.","commonSituations":"Client sends partial update payloads (id + due_at only) for differentiation-tag or group overrides; older API clients still sending group_id instead of set_id.","solutions":["Always include set_id in override payloads sent to the updater service","Merge the persisted override's set_id into the payload before calling the service","Update older clients from group_id to set_id key naming","Rescue Checkpoints::SetIdRequiredError at the API boundary and return 400"],"exampleFix":"// before\nCheckpoints::GroupOverrideUpdaterService.new(checkpoint, { id: id, due_at: t }).call\n// after\nCheckpoints::GroupOverrideUpdaterService.new(checkpoint, { id: id, set_id: override.set_id, due_at: t }).call","handlingStrategy":"validation","validationCode":"payload = { id: override_id }.merge(override_payload)\npayload[:set_id] ||= checkpoint.assignment_overrides.find(override_id).set_id\nCheckpoints::GroupOverrideUpdaterService.new(checkpoint, payload).call","typeGuard":"def override_payload_complete?(payload)\n  payload.is_a?(Hash) && payload.key?(:set_id) && payload[:set_id].present?\nend","tryCatchPattern":"begin\n  Checkpoints::GroupOverrideUpdaterService.new(checkpoint, payload).call\nrescue Checkpoints::SetIdRequiredError => e\n  render json: { error: e.message.presence || 'set_id is required' }, status: :bad_request\nend","preventionTips":["Never send partial override payloads without set_id","Standardize on set_id naming in all client versions","Validate payload keys against a whitelist schema in the controller"],"tags":["rails","checkpoints","group-overrides","missing-parameter"],"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"}