instructure/canvas-lms · error · ArgumentError
Invalid user
Error message
Invalid user
What it means
PageViews::EnqueueQueryService#call raises ArgumentError when the user argument is not an instance of User. The single-user query service needs user.global_id and the user's shard for root account uuids, so it strictly type-checks the argument before building the async request.
Solutions
- Use User.find (raises RecordNotFound) or check the find_by result for nil before calling
- Load the User record from the id: User.find(user_id)
- Validate user.is_a?(User) in the caller and fail with a clearer message
Example fix
// before user = User.find_by(id: params[:user_id]) PageViews::EnqueueQueryService.call(start, end, user, format) // after user = User.find(params[:user_id]) PageViews::EnqueueQueryService.call(start, end, user, format)
Defensive patterns
Strategy: type-guard
Validate before calling
raise ArgumentError, 'user must be a User' unless user.is_a?(User)
Type guard
def loaded_user?(value) value.is_a?(User) end
Try / catch
begin
PageViews::EnqueueQueryService.call(start_date, end_date, user, format)
rescue ArgumentError => e
Rails.logger.warn("page views enqueue rejected: #{e.message}")
end Prevention
- Use User.find instead of find_by when nil is unacceptable
- Check find_by results for nil before use
- Never pass raw ids from controller params without loading
- Guard cached/serialized user data — reload the record
When it happens
Trigger: Calling call(start_date, end_date, user, format) with a user id, a nil (e.g. User.find_by found nothing), a hash, or another model instance.
Common situations: Forwarding the result of User.find_by(email: ...) which can be nil; passing an id string from a controller param; passing a cached serialized user hash.
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
- all elements must be User objects
- 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/b7d578afd7386ada.
Report an issue: GitHub.
Appendix: source
Thrown at app/services/page_views/enqueue_query_service.rb:23
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
module PageViews
class EnqueueQueryService < PageViews::ServiceBase
def call(start_date, end_date, user, format)
raise ArgumentError, "Invalid user" unless user.is_a?(User)
uri = @configuration.uri.merge("/api/v5/pageviews/query")
start_date = parse_date_only(start_date) unless start_date.is_a?(Date)
end_date = parse_date_only(end_date) unless end_date.is_a?(Date)
request = Common::AsyncQueryRequest.new(start_date:, end_date:, user_id: user.global_id, root_account_uuids: cached_root_account_uuids_for(user:), format:)
request.validate!
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
privateView on GitHub (pinned to 1c9f0bb801)