{"record":{"id":"90c133616dc05bd4","repo":"instructure/canvas-lms","slug":"users-must-be-an-array","errorCode":null,"errorMessage":"users must be an array","messagePattern":"users must be an array","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"app/services/page_views/enqueue_batch_query_service.rb","lineNumber":59,"sourceCode":"        format:\n      )\n      request.validate!\n\n      CanvasHttp.post(\n        uri.to_s,\n        request_headers,\n        content_type: \"application/json\",\n        body: request.to_json\n      ) do |response|\n        handle_generic_errors(response) unless response.code.to_i == 201\n        return response.header[\"Location\"].split(\"/\").last\n      end\n    end\n\n    private\n\n    def validate_users!(users)\n      raise ArgumentError, \"users must be an array\" unless users.is_a?(Array)\n      raise ArgumentError, \"users cannot be empty\" if users.empty?\n\n      raise ArgumentError, \"all elements must be User objects\" unless users.all?(User)\n    end\n\n    def parse_date_only(date_string)\n      raise ArgumentError, \"Date must be in YYYY-MM-DD format\" unless date_string.match?(/\\A\\d{4}-\\d{2}-\\d{2}\\z/)\n\n      Date.parse(date_string)\n    end\n\n    def collect_root_account_uuids(users)\n      users.flat_map do |user|\n        user.shard.activate do\n          user.root_account_ids.map do |id|\n            Account.find_cached(id).uuid\n          end\n        end","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/page_views/enqueue_batch_query_service.rb#L41-L77","documentation":"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.","triggerScenarios":"Calling PageViews::EnqueueBatchQueryService.call with users = nil, a single User object, an ActiveRecord relation, a hash, or any other non-Array value.","commonSituations":"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.","solutions":["Wrap a single user in an array: [user]","Convert ActiveRecord relations with .to_a before calling","Load User objects from ids: User.where(id: ids).to_a (must be User instances, not ids)","Add a guard in the caller to skip or raise a clearer error when users is nil"],"exampleFix":"// before\nPageViews::EnqueueBatchQueryService.call(start_date, end_date, user, format)\n// after\nPageViews::EnqueueBatchQueryService.call(start_date, end_date, [user], format)","handlingStrategy":"type-guard","validationCode":"raise ArgumentError, 'users must be an array of User' unless users.is_a?(Array) && users.all?(User) && users.any?","typeGuard":"def user_array?(value)\n  value.is_a?(Array) && value.all?(User)\nend","tryCatchPattern":"begin\n  PageViews::EnqueueBatchQueryService.call(start_date, end_date, users, format)\nrescue ArgumentError => e\n  Rails.logger.warn(\"page views batch enqueue rejected: #{e.message}\")\nend","preventionTips":["Always pass arrays of loaded User records, not ids or relations","Use .to_a on ActiveRecord relations before calling","Compact nils out of user collections","Write a spec asserting ArgumentError for nil/single-user/empty inputs"],"tags":["ruby","argument-validation","page-views"],"backgroundTag":"invalid-argument-value","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}