instructure/canvas-lms · error · ActiveRecord::RecordNotFound
Context must be of type '#
Error message
Context must be of type '#{klass}' What it means
process_user_observer raises this ImportError when student_id equals observer_id — a user cannot be their own observer. The check is a plain string equality on the two SIS IDs, done before any DB lookups, so even identical IDs that resolve to no user still raise this rather than a not-found error.
Solutions
- Correct the observer_id in the row to a different user's SIS ID.
- Filter self-pairings out in the pre-import validation step.
- If self-observation was intended as a no-op, omit the row entirely.
Example fix
// before (CSV) user_id,observer_id STU001,STU001 // after user_id,observer_id STU001,OBS009
Defensive patterns
Strategy: validation
Validate before calling
raise 'observer cannot observe themselves' if observer_id.to_s == student_id.to_s
Try / catch
begin
importer.process_user_observer(obs_id, stu_id, status)
rescue SIS::Import::ImportError => e
logger.warn("skipped row: #{e.message}")
end Prevention
- Assert observer_id != student_id in your ETL pipeline.
- Watch for copy/fill-down errors in spreadsheets when generating CSVs.
- Use distinct variables/sources for observer and student IDs in scripts.
When it happens
Trigger: A users_observers CSV row where the observer_id and user_id columns contain the same SIS ID (copy-paste error); calling process_user_observer('X', 'X', 'active') programmatically.
Common situations: Spreadsheet fill-down copying the student's own ID into the observer column; bulk scripts that compute observer_id from the same variable as student_id; parents provisioned with a single SIS ID used for both roles.
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
- Cannot find # for ID: #
- Context is required, but none found
- No account found for context
- A user did not pass validation
- An email did not pass validation
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/9b55df8eb9ac724d.
Report an issue: GitHub.
Appendix: source
Thrown at app/controllers/application_controller.rb:1479
end
def require_context_and_read_access
require_context && authorized_action(@context, @current_user, :read)
end
helper_method :clean_return_to
def require_account_context
require_context_type(Account)
end
def require_course_context
require_context_type(Course)
end
def require_context_type(klass)
unless require_context && @context.is_a?(klass)
raise ActiveRecord::RecordNotFound, "Context must be of type '#{klass}'"
end
true
end
MAX_ACCOUNT_LINEAGE_TO_SHOW_IN_CRUMBS = 3
# Can be used as a before_action, or just called from controller code.
# Assigns the variable @context to whatever context the url is scoped
# to. So /courses/5/assignments would have a @context=Course.find(5).
# Also assigns @context_membership to the membership type of @current_user
# if @current_user is a member of the context.
def get_context(user_scope: nil)
GuardRail.activate(:secondary) do
unless @context
if params[:course_id]
course_scope = @token ? Course : Course.active
@context = api_find(course_scope, params[:course_id])View on GitHub (pinned to 1c9f0bb801)