instructure/canvas-lms · error · ArgumentError

users must be an array

Error message

users must be an array

What it means

PageViews::EnqueueBatchQueryService#validate_users! raises ArgumentError when the users argument passed to call is not an Array. The service batches page view queries for many users, so it requires an array to iterate over. Any non-array value (nil, a single User, a relation) fails this check immediately before any HTTP work happens.

Solutions

  1. Wrap a single user in an array: [user]
  2. Convert ActiveRecord relations with .to_a before calling
  3. Load User objects from ids: User.where(id: ids).to_a (must be User instances, not ids)
  4. Add a guard in the caller to skip or raise a clearer error when users is nil

Example fix

// before
PageViews::EnqueueBatchQueryService.call(start_date, end_date, user, format)
// after
PageViews::EnqueueBatchQueryService.call(start_date, end_date, [user], format)
Defensive patterns

Strategy: type-guard

Validate before calling

raise ArgumentError, 'users must be an array of User' unless users.is_a?(Array) && users.all?(User) && users.any?

Type guard

def user_array?(value)
  value.is_a?(Array) && value.all?(User)
end

Try / catch

begin
  PageViews::EnqueueBatchQueryService.call(start_date, end_date, users, format)
rescue ArgumentError => e
  Rails.logger.warn("page views batch enqueue rejected: #{e.message}")
end

Prevention

When it happens

Trigger: Calling PageViews::EnqueueBatchQueryService.call with users = nil, a single User object, an ActiveRecord relation, a hash, or any other non-Array value.

Common situations: Passing one User instead of wrapping it in an array; passing user_ids integers instead of User objects; forgetting that scope results are relations not arrays (e.g. User.where(...)); a nil from an earlier lookup being forwarded.

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/90c133616dc05bd4. Report an issue: GitHub.

Appendix: source

Thrown at app/services/page_views/enqueue_batch_query_service.rb:59

        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

    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

View on GitHub (pinned to 1c9f0bb801)