{"record":{"id":"d5bd0f7eeb0054e8","repo":"Freika/dawarich","slug":"no-date-range-specified","errorCode":null,"errorMessage":"No date range specified","messagePattern":"No date range specified","errorType":"http","errorClass":"Maps::BoundsCalculator::NoDateRangeError","httpStatus":400,"severity":"error","filePath":"app/services/maps/bounds_calculator.rb","lineNumber":32,"sourceCode":"    def call\n      validate_inputs!\n\n      start_timestamp = parse_date_parameter(@start_date)\n      end_timestamp = parse_date_parameter(@end_date)\n\n      bounds_result = execute_bounds_query(start_timestamp, end_timestamp)\n      point_count = bounds_result['point_count'].to_i\n\n      return build_no_data_response if point_count.zero?\n\n      build_success_response(bounds_result, point_count)\n    end\n\n    private\n\n    def validate_inputs!\n      raise NoUserFoundError, I18n.t('services.maps.bounds_calculator.no_user') unless @user\n      raise NoDateRangeError, I18n.t('services.maps.bounds_calculator.no_date_range') unless @start_date && @end_date\n    end\n\n    def execute_bounds_query(start_timestamp, end_timestamp)\n      ActiveRecord::Base.connection.exec_query(\n        \"SELECT COUNT(*) as point_count,\n                ST_YMin(ST_Extent(lonlat::geometry)) as min_lat,\n                ST_YMax(ST_Extent(lonlat::geometry)) as max_lat,\n                ST_XMin(ST_Extent(lonlat::geometry)) as min_lng,\n                ST_XMax(ST_Extent(lonlat::geometry)) as max_lng\n         FROM points\n         WHERE user_id = $1\n         AND timestamp BETWEEN $2 AND $3\",\n        'bounds_query',\n        [@user.id, start_timestamp, end_timestamp]\n      ).first\n    end\n\n    def build_success_response(bounds_result, point_count)","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/Freika/dawarich/blob/97fad417c5a11b0eb11157890635e015723a2e97/app/services/maps/bounds_calculator.rb#L14-L50","documentation":"Maps::BoundsCalculator::NoDateRangeError raised in validate_inputs! when start_date or end_date is nil. The bounds SQL uses `timestamp BETWEEN $2 AND $3`, so both ends of the range are mandatory; the validator rejects the call before touching the database. Note Ruby truthiness: an empty string '' passes this check and instead fails later in parse_date_parameter with invalid_date - only a truly absent/nil parameter triggers this error.","triggerScenarios":"Calling the maps bounds API/service with start_date or end_date missing from the request, a caller passing nil explicitly, or frontend code firing the request before date pickers have been initialized so the params were never appended to the query string.","commonSituations":"Hand-crafted curl calls omitting params, URL builders that drop empty values, or clients assuming the service defaults to 'all time'.","solutions":["Supply both start_date and end_date - each may be a unix epoch integer, a digit-string, or a time string Time.zone.parse understands","Fix the client to always send both parameters","If a sensible default exists (e.g. first-of-month to today), default the values in the controller before calling the service"],"exampleFix":"# before\nMaps::BoundsCalculator.new(user: user, start_date: params[:start_at], end_date: params[:end_at]).call\n# params[:end_at] absent -> NoDateRangeError\n\n# after\nstart_date = params[:start_at].presence || 30.days.ago.to_i\nend_date   = params[:end_at].presence   || Time.current.to_i\nMaps::BoundsCalculator.new(user: user, start_date: start_date, end_date: end_date).call","handlingStrategy":"validation","validationCode":"# present? (not truthiness) also catches empty strings before they become invalid_date\nraise ArgumentError, 'start_date and end_date required' if start_date.blank? || end_date.blank?","typeGuard":"def complete_date_range?(start_date, end_date)\n  !start_date.nil? && !end_date.nil?\nend","tryCatchPattern":"begin\n  Maps::BoundsCalculator.new(user: u, start_date: s, end_date: e).call\nrescue Maps::BoundsCalculator::NoDateRangeError => e\n  render json: { error: e.message }, status: :bad_request\nend","preventionTips":["Treat both dates as required params in the route/API contract and document it","Send epoch integers from clients to skip string parsing entirely","Use presence-based checks in callers - Ruby truthiness lets '' slip through to a different error"],"tags":["maps","validation","missing-parameters","bounds"],"backgroundTag":"missing-required-parameter","analyzedSha":"97fad417c5a11b0eb11157890635e015723a2e97","analyzedAt":"2026-08-21T17:04:17.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}