instructure/canvas-lms · error · ArgumentError
all elements must be User objects
Error message
all elements must be User objects
What it means
PageViews::EnqueueBatchQueryService#validate_users! raises ArgumentError when any element of the users array is not a User instance. The service uses each element's global_id and shard associations, so plain ids, hashes, or other records are rejected. Duck typing is not accepted; the check is users.all?(User).
Solutions
- Load records first: User.where(id: ids).to_a
- Compact the array to remove nils before calling
- Map ids to User objects and verify all loaded (check count vs ids.uniq.count)
Example fix
// before PageViews::EnqueueBatchQueryService.call(start, end, user_ids, format) // after users = User.where(id: user_ids).to_a PageViews::EnqueueBatchQueryService.call(start, end, users, format)
Defensive patterns
Strategy: type-guard
Validate before calling
users = User.where(id: user_ids).to_a raise ArgumentError, 'not all users loaded' unless users.size == user_ids.uniq.size
Type guard
def all_users?(value) value.is_a?(Array) && value.all?(User) end
Try / catch
begin
service.call(start_date, end_date, users, format)
rescue ArgumentError => e
Rails.logger.error("invalid users argument: #{e.message}")
end Prevention
- Never pass pluck/select results — load full User records
- Convert ids to records with User.where(id: ids).to_a
- Verify loaded count matches requested ids
- Compact nils from find_by-style lookups
When it happens
Trigger: Calling call(start_date, end_date, [1, 2, 3]) with integer/global ids, [user.id], [user.attributes], or an array containing a mix of User objects and nils.
Common situations: Passing user ids collected from a form or API payload instead of loaded records; loading via select/pluck which returns raw values; forgetting nil entries after a compact-less filter.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Invalid user
- Date must be in YYYY-MM-DD format
- Date must be in YYYY-MM-DD format
- Must have a domain and a user to build a JWT
- progress_tracking must be a boolean
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/025da3fb6d6e352a.
Report an issue: GitHub.
Appendix: source
Thrown at app/services/page_views/enqueue_batch_query_service.rb:62
CanvasHttp.post(
uri.to_s,
request_headers,
content_type: "application/json",
body: request.to_json
) do |response|
handle_generic_errors(response) unless response.code.to_i == 201
return response.header["Location"].split("/").last
end
end
private
def validate_users!(users)
raise ArgumentError, "users must be an array" unless users.is_a?(Array)
raise ArgumentError, "users cannot be empty" if users.empty?
raise ArgumentError, "all elements must be User objects" unless users.all?(User)
end
def parse_date_only(date_string)
raise ArgumentError, "Date must be in YYYY-MM-DD format" unless date_string.match?(/\A\d{4}-\d{2}-\d{2}\z/)
Date.parse(date_string)
end
def collect_root_account_uuids(users)
users.flat_map do |user|
user.shard.activate do
user.root_account_ids.map do |id|
Account.find_cached(id).uuid
end
end
end.uniq
end
endView on GitHub (pinned to 1c9f0bb801)