{"record":{"id":"ab331f982067f702","repo":"instructure/canvas-lms","slug":"each-date-must-have-a-type-specified-everyone-or-override","errorCode":null,"errorMessage":"each date must have a type specified ('everyone' or 'override')","messagePattern":"each date must have a type specified \\('everyone' or 'override'\\)","errorType":"exception","errorClass":"Checkpoints::DateTypeRequiredError","httpStatus":null,"severity":"error","filePath":"app/services/checkpoints/discussion_checkpoint_common_service.rb","lineNumber":46,"sourceCode":"    @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\n    %w[\n      assignment_group_id\n      context_id\n      context_type\n      description\n      grade_group_students_individually\n      grading_type\n      grading_standard_id\n      group_category","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/checkpoints/discussion_checkpoint_common_service.rb#L28-L64","documentation":"DiscussionCheckpointCommonService#validate_dates iterates @dates and requires each date hash to include a non-blank :type ('everyone' or 'override'). A blank type raises DateTypeRequiredError. The type field drives which date list the entry belongs to (section-level 'everyone' dates vs per-student 'override' dates).","triggerScenarios":"Passing a dates array containing an element without :type, or with type set to nil/\"\", e.g. dates: [{due_at: t}] or [{type: nil}].","commonSituations":"Frontend sending date objects with only due_at/unlock_at for the 'everyone' entry without tagging type; legacy payloads built before the type field was introduced; hand-written JSON in API calls missing the type key.","solutions":["Add type: 'everyone' or type: 'override' to every date hash in the payload.","Add presence-of-type validation on the client/controller before calling the service.","Check any bulk/loop code building dates isn't dropping the type key for some entries."],"exampleFix":"// before\ndates: [{ due_at: '2026-01-01' }]\n// after\ndates: [{ type: 'everyone', due_at: '2026-01-01' }]","handlingStrategy":"validation","validationCode":"dates.each { |d| raise ArgumentError, 'date type required' if d[:type].blank? }","typeGuard":"def typed_dates?(dates)\n  dates.is_a?(Array) && dates.all? { |d| d.is_a?(Hash) && !d[:type].blank? }\nend","tryCatchPattern":"begin\n  service.call(...)\nrescue Checkpoints::DateTypeRequiredError => e\n  render json: { error: e.message }, status: :bad_request\nend","preventionTips":["Define date payloads with a shared schema/type in the frontend","Default 'everyone' type for unscoped dates at payload build time","Add presence validation before each service call"],"tags":["ruby","canvas","validation","checkpoints"],"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"}