instructure/canvas-lms · error

cannot call enrollment_state on a new record

Error message

cannot call enrollment_state on a new record

What it means

Enrollment#enrollment_state overrides the enrollment_state association reader and refuses to run on unsaved records, because the EnrollmentState row is derived from persisted enrollment data; reading it for a new_record? would be meaningless. create_enrollment_state and other code must therefore only call this on persisted enrollments.

Solutions

  1. Save the enrollment before reading enrollment_state
  2. Guard with return if enrollment.new_record? before accessing enrollment_state
  3. Use enrollment_state_overrides/computed state helpers that work on unsaved records if you need predicted state
  4. In specs, create! the enrollment instead of building it

Example fix

// before
state = enrollment.enrollment_state # raises for new record
// after
state = enrollment.new_record? ? nil : enrollment.enrollment_state
Defensive patterns

Strategy: type-guard

Validate before calling

next if enrollment.new_record?
state = enrollment.enrollment_state

Type guard

def persisted_enrollment?(enrollment)
  enrollment.is_a?(Enrollment) && !enrollment.new_record?
end

Try / catch

begin
  state = enrollment.enrollment_state
rescue RuntimeError => e
  raise unless e.message =~ /new record/
  state = nil
end

Prevention

When it happens

Trigger: Calling enrollment.enrollment_state on a build/new Enrollment that has not been saved — e.g. computing state before create, or create_enrollment_state invoked on an unsaved enrollment in a callback-order bug.

Common situations: Specs calling enrollment_state on Enrollment.new; after_build-style code touching enrollment_state before save; code paths that construct transient enrollments for previews or invitations.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/5be538f02d64f036. Report an issue: GitHub.

Appendix: source

Thrown at app/models/enrollment.rb:842

    end

    state :deleted
    state :rejected do
      event :unreject, transitions_to: :invited
    end
    state :completed

    # Inactive is a "hard" state, i.e. tuition not paid
    state :inactive
  end

  def enrollment_dates
    Canvas::Builders::EnrollmentDateBuilder.preload([self]) unless @enrollment_dates
    @enrollment_dates
  end

  def enrollment_state
    raise "cannot call enrollment_state on a new record" if new_record?

    result = super
    unless result
      association(:enrollment_state).reload
      result = super
    end
    # ensure we have an enrollment state object present with a reverse association
    result ||= create_enrollment_state
    result.enrollment = self
    result
  end

  def create_enrollment_state
    self.enrollment_state =
      shard.activate do
        GuardRail.activate(:primary) do
          EnrollmentState.unique_constraint_retry do
            EnrollmentState.where(enrollment_id: self).first_or_create

View on GitHub (pinned to 1c9f0bb801)