instructure/canvas-lms · error · ImportError

An observer referenced a non-existent user #

Error message

An observer referenced a non-existent user #{observer_id}

What it means

Referential-integrity error in UserObserverImporter::Work#process_user_observer raised when observer_id is present but no matching user exists in the root account (not previously imported and not resolvable). The observer link cannot be created, so the row fails.

Solutions

  1. Import the observer user before the user_observers file
  2. Verify the observer_id matches the user's sis_source_id
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at lib/sis/user_observer_importer.rb:64 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at lib/sis/user_observer_importer.rb:64

      def initialize(batch, root_account, logger)
        @batch = batch
        @root_account = root_account
        @logger = logger
        @success_count = 0

        @users_to_update_account_associations = Set.new
        @user_observers_to_update_sis_batch_ids = []
      end

      def process_user_observer(observer_id, student_id, status)
        raise ImportError, "No observer_id given for a user observer" if observer_id.blank?
        raise ImportError, "No user_id given for a user observer" if student_id.blank?
        raise ImportError, "Can't observe yourself user #{student_id}" if student_id == observer_id
        raise ImportError, "Improper status \"#{status}\" for a user_observer" unless /\A(active|deleted)\z/i.match?(status)
        return if @batch.skip_deletes? && status =~ /deleted/i

        o_pseudo = @root_account.pseudonyms.active.find_by(sis_user_id: observer_id)
        raise ImportError, "An observer referenced a non-existent user #{observer_id}" unless o_pseudo

        s_pseudo = @root_account.pseudonyms.active.find_by(sis_user_id: student_id)
        raise ImportError, "A student referenced a non-existent user #{student_id}" unless s_pseudo

        observer = o_pseudo.user
        student = s_pseudo.user
        raise ImportError, "Can't observe yourself user #{student_id}" if observer == student

        add_remove_observer(observer, student, observer_id, student_id, status)
      end

      def add_remove_observer(observer, student, observer_id, student_id, status)
        case status.downcase
        when "active"
          check_observer_notification_settings(observer)
          user_observer = UserObservationLink.create_or_restore(observer:, student:, root_account: @root_account)
        when "deleted"
          user_observer = observer.as_observer_observation_links.for_root_accounts(@root_account).find_by(user_id: student)

View on GitHub (pinned to 1c9f0bb801)