Freika/dawarich · error · Maps::BoundsCalculator::NoUserFoundError

No user found

Error message

No user found

What it means

Maps::BoundsCalculator::NoUserFoundError raised in validate_inputs! when the user: keyword argument is nil. The service immediately runs a raw SQL bounds query against points scoped to @user.id, so a nil user is rejected up front with 'No user found' instead of producing a broken query or another user's bounds.

Source

Thrown at app/services/maps/bounds_calculator.rb:31

    def call
      validate_inputs!

      start_timestamp = parse_date_parameter(@start_date)
      end_timestamp = parse_date_parameter(@end_date)

      bounds_result = execute_bounds_query(start_timestamp, end_timestamp)
      point_count = bounds_result['point_count'].to_i

      return build_no_data_response if point_count.zero?

      build_success_response(bounds_result, point_count)
    end

    private

    def validate_inputs!
      raise NoUserFoundError, I18n.t('services.maps.bounds_calculator.no_user') unless @user
      raise NoDateRangeError, I18n.t('services.maps.bounds_calculator.no_date_range') unless @start_date && @end_date
    end

    def execute_bounds_query(start_timestamp, end_timestamp)
      ActiveRecord::Base.connection.exec_query(
        "SELECT COUNT(*) as point_count,
                ST_YMin(ST_Extent(lonlat::geometry)) as min_lat,
                ST_YMax(ST_Extent(lonlat::geometry)) as max_lat,
                ST_XMin(ST_Extent(lonlat::geometry)) as min_lng,
                ST_XMax(ST_Extent(lonlat::geometry)) as max_lng
         FROM points
         WHERE user_id = $1
         AND timestamp BETWEEN $2 AND $3",
        'bounds_query',
        [@user.id, start_timestamp, end_timestamp]
      ).first
    end

View on GitHub (pinned to 97fad417c5)

Solutions

  1. Verify the user object is loaded and persisted before calling the service
  2. If triggered via API key, confirm the key still belongs to an existing user
  3. Re-authenticate / refresh the session and retry
  4. Guard the caller: skip or 401 when the user cannot be resolved instead of passing nil through

Example fix

# before
calculator = Maps::BoundsCalculator.new(user: current_user, ...)  # current_user can be nil

# after
return head :unauthorized if current_user.nil?
calculator = Maps::BoundsCalculator.new(user: current_user, ...)
Defensive patterns

Strategy: type-guard

Validate before calling

raise ArgumentError, 'user required' unless user.is_a?(User) && user.persisted?

Type guard

def boundable_user?(candidate)
  candidate.is_a?(User) && candidate.persisted? && !candidate.destroyed?
end

Try / catch

begin
  Maps::BoundsCalculator.new(user: user, start_date: s, end_date: e).call
rescue Maps::BoundsCalculator::NoUserFoundError
  head :unauthorized
end

Prevention

When it happens

Trigger: Instantiating Maps::BoundsCalculator.new(user: nil, start_date:, end_date:) - e.g. an API key that no longer maps to an existing user, current_user evaluating to nil in an unauthenticated controller path, or the user record being destroyed between authentication and the service call (background jobs holding a stale id).

Common situations: Deleted or archived accounts with still-valid sessions/API keys, jobs resolving a user id that was later destroyed, or a controller missing its authentication before_action.

Related errors


AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21). Data as JSON: /api/errors/b4da2a7a96d5a2a3. Report an issue: GitHub.