Freika/dawarich · error · ArgumentError
Invalid date format: %{value}
Error message
Invalid date format: %{value} What it means
ArgumentError raised inside parse_date_parameter when a String date parameter is not purely digits and Time.zone.parse returns nil - ActiveSupport could not interpret it as a datetime at all. The %{value} placeholder carries the offending string. Note this raise happens inside a method that immediately rescues ArgumentError and re-raises from line 89, so the observable failure is the identical invalid_date message from the rescue clause.
Source
Thrown at app/services/maps/bounds_calculator.rb:78
}
end
def build_no_data_response
{
success: false,
error: I18n.t('services.maps.bounds_calculator.no_data_found_for_the_specified_date_range'),
point_count: 0
}
end
def parse_date_parameter(param)
case param
when String
if param.match?(/^\d+$/)
param.to_i
else
parsed_time = Time.zone.parse(param)
raise ArgumentError, I18n.t('services.maps.bounds_calculator.invalid_date', value: param) if parsed_time.nil?
parsed_time.to_i
end
when Integer
param
else
param.to_i
end
rescue ArgumentError => e
Rails.logger.error "Invalid date format: #{param} - #{e.message}"
raise ArgumentError, I18n.t('services.maps.bounds_calculator.invalid_date', value: param)
end
end
end
View on GitHub (pinned to 97fad417c5)
Solutions
- Send dates as unix epoch timestamps (integer or digit-only string) - the unambiguous fast path
- Or use ISO 8601 strings like '2024-06-01T00:00:00Z' that Time.zone.parse always handles
- Validate/normalize date inputs on the client before issuing the request
- Rescue ArgumentError at the controller and return 400 with the message rather than letting it bubble as 500
Example fix
# before calculator = Maps::BoundsCalculator.new(user: u, start_date: 'June 1 2024', end_date: 'todayish') # after calculator = Maps::BoundsCalculator.new(user: u, start_date: 1717200000, end_date: 1719791999)
Defensive patterns
Strategy: validation
Validate before calling
def parseable_bound_date?(value)
case value
when Integer then true
when String then value.match?(/\A\d+\z/) || !Time.zone.parse(value).nil?
else false
end
end
raise ArgumentError, "bad date #{start_date}" unless parseable_bound_date?(start_date) Type guard
def epoch_or_iso?(value)
value.is_a?(Integer) || value.to_s.match?(/\A\d+\z\z/) || value.to_s.match?(\A\d{4}-\d{2}-\d{2}(T[\d:.]+Z)?\z/)
end Try / catch
begin
result = Maps::BoundsCalculator.new(user: u, start_date: s, end_date: e).call
rescue ArgumentError => e
render json: { error: e.message }, status: :bad_request # message includes the offending %{value}
end Prevention
- Send unix epoch integers - the digit-string/Integer fast path never parses
- Otherwise use ISO 8601 ('2024-06-01T00:00:00Z')
- Validate in the client with the same contract before issuing the request
When it happens
Trigger: Passing date strings like 'not-a-date', '2024-13-01' (month 13 makes parse return nil in many zones), 'YYYY/MM/DD' variants ActiveSupport cannot resolve, or URL-encoding damage that mangles the parameter. Digit strings ('1717200000') and Integers never hit this path.
Common situations: Hand-crafted API calls, locale-specific formats (DD/MM/YYYY vs MM/DD/YYYY ambiguity), or test fixtures using placeholder strings like 'foo'.
Related errors
AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21).
Data as JSON: /api/errors/c32da336fb14e4c3.
Report an issue: GitHub.