instructure/canvas-lms · error · ArgumentError
Date must be in YYYY-MM-DD format
Error message
Date must be in YYYY-MM-DD format
What it means
PageViews::EnqueueQueryService#parse_date_only raises ArgumentError when a date string does not match the strict YYYY-MM-DD regex (/\A\d{4}-\d{2}-\d{2}\z/). This mirrors the batch service: the page views API requires date-only values, so strings are validated before Date.parse. Only applied when the argument is not already a Date.
Solutions
- Pass Date objects instead of strings
- Normalize with Date.parse(value).iso8601 before calling
- For timestamps, take the date part: timestamp.to_date.iso8601
- Validate controller params with a YYYY-MM-DD format check
Example fix
// before
service.call('2026-09-15T10:00:00Z', end_date, user, format)
// after
service.call(Date.parse('2026-09-15T10:00:00Z').iso8601, end_date, user, format) Defensive patterns
Strategy: validation
Validate before calling
raise ArgumentError, 'date must be YYYY-MM-DD or Date' unless start_date.is_a?(Date) || start_date.to_s.match?(/\A\d{4}-\d{2}-\d{2}\z/) Type guard
def date_only?(value)
value.is_a?(Date) || (value.is_a?(String) && value.match?(/\A\d{4}-\d{2}-\d{2}\z/))
end Try / catch
begin
service.call(start_date, end_date, user, format)
rescue ArgumentError => e
Rails.logger.warn("invalid page view query dates: #{e.message}")
end Prevention
- Pass Date objects directly when you already have them
- Convert timestamps with .to_date.iso8601
- Validate date params at the controller boundary with a format regex
- Avoid locale-dependent date formatting before API calls
When it happens
Trigger: Passing start_date or end_date as '15-09-2026', '2026/09/15', an ISO timestamp '2026-09-15T10:00:00Z', or a string with whitespace to call.
Common situations: Copying dates from logs including time; localized input formats; JSON payloads carrying full ISO 8601 timestamps; single-digit months/days.
Related errors
- Date must be in YYYY-MM-DD format
- all elements must be User objects
- Invalid user
- Must have a domain and a user to build a JWT
- users cannot be empty
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/40f155c82749c138.
Report an issue: GitHub.
Appendix: source
Thrown at app/services/page_views/enqueue_query_service.rb:44
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
private
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 cached_root_account_uuids_for(user:)
user.shard.activate do
user.root_account_ids.map do |id|
Account.find_cached(id).uuid
end
end
end
end
end
View on GitHub (pinned to 1c9f0bb801)