opf/openproject · error · ActiveRecord::RecordNotFound

Couldn't find WeekDay with day #{day}

Error message

Couldn't find WeekDay with day #{day}

What it means

WeekDay is a plain Ruby value class (not ActiveRecord) representing weekdays, with DAY_RANGE = 1..7. The class-level find_by! mimics ActiveRecord finder semantics but simply raises ActiveRecord::RecordNotFound unless the given day is within 1..7. Note the convention: OpenProject's WeekDay numbering is Monday=1..Sunday=7, matching Date#cwday, not Date#wday (Sunday=0).

Source

Thrown at app/models/week_day.rb:38

# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++

class WeekDay
  DAY_RANGE = Array(1..7)

  attr_accessor :day

  class << self
    def find_by!(day:)
      raise ActiveRecord::RecordNotFound, "Couldn't find WeekDay with day #{day}" unless day.in?(DAY_RANGE)

      new(day:)
    end

    def all
      DAY_RANGE.map do |day|
        new(day:)
      end
    end
  end

  def initialize(day:)
    self.day = day
  end

  def name
    day_names = I18n.t("date.day_names")
    day_names[day % 7]

View on GitHub (pinned to d9742c43f3)

Solutions

  1. Pass a commercial weekday: use date.cwday (1..7) instead of date.wday (0..6).
  2. If your input is 0-based wday, convert first: wday.zero? ? 7 : wday.
  3. Guard user/system input with day.between?(1, 7) before calling find_by!.

Example fix

# before
WeekDay.find_by!(day: date.wday)   # raises for Sunday (0)

# after
WeekDay.find_by!(day: date.cwday)  # Monday=1..Sunday=7
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, "day must be 1..7, got #{day}" unless day.is_a?(Integer) && day.between?(1, 7)

Type guard

def week_day_number?(value)
  value.is_a?(Integer) && value.between?(1, 7)
end

Try / catch

begin
  WeekDay.find_by!(day: day)
rescue ActiveRecord::RecordNotFound
  WeekDay.find_by!(day: 1) # or map wday: value.zero? ? 7 : value
end

Prevention

When it happens

Trigger: Calling WeekDay.find_by!(day: 0) or find_by!(day: 8) — most commonly by passing Date#wday (0..6, Sunday=0) instead of Date#cwday (1..7, Monday=1), e.g. in non-working-day calculations for duration/working-hours logic.

Common situations: Developers convert Ruby's standard wday to this API without remapping the index; parsing day numbers from external systems that use 0-based weeks; off-by-one when looping 0..7 over days.

Related errors


AI-assisted analysis of opf/openproject@d9742c43f3 (2026-08-21). Data as JSON: /api/errors/963b022cab76e7ac. Report an issue: GitHub.