we-promise/sure · warning · Api::V1::SecurityResourceFiltering::InvalidFilterError

#{key} must be an ISO 8601 date

Error message

#{key} must be an ISO 8601 date

What it means

Api::V1::SecurityResourceFiltering (app/controllers/concerns/api/v1/security_resource_filtering.rb:47-52) supplies parse_date_param to the securities and security_prices index actions. It uses strict Date.iso8601; failures raise ArgumentError, converted by invalid_filter! into InvalidFilterError '<key> must be an ISO 8601 date', which each controller rescues to 422 validation_failed.

Source

Thrown at app/controllers/concerns/api/v1/security_resource_filtering.rb:51

    end

    def parse_boolean_filter_param(key)
      normalized_value = params[key].to_s.strip.downcase

      invalid_filter!("#{key} must be true or false") if normalized_value.blank?
      return BOOLEAN_FILTERS.fetch(normalized_value) if BOOLEAN_FILTERS.key?(normalized_value)

      invalid_filter!("#{key} must be true or false")
    end

    def parse_date_param(key)
      Date.iso8601(params[key].to_s)
    rescue ArgumentError
      invalid_filter!("#{key} must be an ISO 8601 date")
    end

    def invalid_filter!(message)
      raise InvalidFilterError, message
    end
end

View on GitHub (pinned to e69894adb9)

Solutions

  1. Send date filters as strict YYYY-MM-DD on /securities and /security_prices
  2. Centralize one date-formatting helper that always emits ISO 8601 dates
  3. Validate with Date.iso8601 client-side before the request
  4. Read the 422 message — it names the exact failing param

Example fix

# before
GET /api/v1/securities?start_date=31-01-2024
# after
GET /api/v1/securities?start_date=2024-01-31
Defensive patterns

Strategy: validation

Validate before calling

require 'date'
%i[start_date end_date].each do |k|
  next if filters[k].to_s.strip.empty?
  Date.iso8601(filters[k]) # strict YYYY-MM-DD or raise
end

Type guard

def valid_iso_date?(v) = v.to_s.match?(/\A\d{4}-\d{2}-\d{2}\z/)

Try / catch

begin
  client.get('/api/v1/securities', filters)
rescue Faraday::UnprocessableEntity => e
  # 422 — body message says '<key> must be an ISO 8601 date'
end

Prevention

When it happens

Trigger: GET /api/v1/securities?start_date=2024/01/31 or GET /api/v1/security_prices?end_date=Jan 31 — any date filter on those endpoints that is not strict YYYY-MM-DD.

Common situations: Shared client code sending US or slash-formatted dates to every index endpoint uniformly; spreadsheet-exported dates with locale formatting; timestamps reused from holdings' more lenient Date.parse behavior.

Related errors


AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21). Data as JSON: /api/errors/fcb992fc84965cba. Report an issue: GitHub.