we-promise/sure · error · Provider::Mercury::MercuryError

not_found

not_found

Error message

Resource not found

What it means

Raised by Provider::Mercury#handle_response when Mercury returns HTTP 404, meaning the requested resource does not exist on Mercury's side. In this client it can only come from get_account or get_account_transactions, where the account ID is interpolated into the URL path (URL-encoded).

Source

Thrown at app/models/provider/mercury.rb:124

        "Accept" => "application/json"
      }
    end

    def handle_response(response)
      case response.code
      when 200
        JSON.parse(response.body, symbolize_names: true)
      when 400
        Rails.logger.error "Mercury API: Bad request - #{response.body}"
        raise MercuryError.new("Bad request to Mercury API: #{response.body}", :bad_request)
      when 401
        # Parse the error response for more specific messages
        error_message = parse_error_message(response.body)
        raise MercuryError.new(error_message, :unauthorized)
      when 403
        raise MercuryError.new("Access forbidden - check your API token permissions", :access_forbidden)
      when 404
        raise MercuryError.new("Resource not found", :not_found)
      when 429
        raise MercuryError.new("Rate limit exceeded. Please try again later.", :rate_limited)
      else
        Rails.logger.error "Mercury API: Unexpected response - Code: #{response.code}, Body: #{response.body}"
        raise MercuryError.new("Failed to fetch data: #{response.code} #{response.message} - #{response.body}", :fetch_failed)
      end
    end

    def parse_error_message(body)
      parsed = JSON.parse(body, symbolize_names: true)
      errors = parsed[:errors] || {}

      case errors[:errorCode]
      when "ipNotWhitelisted"
        ip = errors[:ip] || "unknown"
        "IP address not whitelisted (#{ip}). Add your IP to the API token's whitelist in Mercury dashboard."
      when "noTokenInDBButMaybeMalformed"
        "Invalid token format. Make sure to include the 'secret-token:' prefix."

View on GitHub (pinned to e69894adb9)

Solutions

  1. Call get_accounts and verify the account_id is still in the returned list; if missing, remove or deactivate the local record for it.
  2. Check the stored ID for whitespace/newlines and exact UUID formatting before passing it.
  3. Confirm you used the API account id field (not the dashboard display ID or the last-4 digits).
  4. Verify base_url — a wrong base URL can turn a valid path into a 404.

Example fix

# before
provider.get_account_transactions(account_id, start_date: 30.days.ago)

# after
ids = provider.get_accounts[:accounts].map { |a| a[:id] }
if ids.include?(account_id)
  provider.get_account_transactions(account_id, start_date: 30.days.ago)
else
  Rails.logger.info "Mercury account #{account_id} no longer exists; skipping"
end
Defensive patterns

Strategy: validation

Validate before calling

account_id = account_id.to_s.strip
unless account_id.match?(/\A[0-9a-f-]{36}\z/i) # Mercury UUID
  raise ArgumentError, "not a Mercury account id: #{account_id.inspect}"
end

Try / catch

begin
  provider.get_account_transactions(account_id, start_date: start)
rescue Provider::Mercury::MercuryError => e
  if e.error_type == :not_found
    account.disable!(reason: "missing_at_provider")
  else
    raise
  end
end

Prevention

When it happens

Trigger: get_account(account_id) with an ID that was deleted or never existed; get_account_transactions with a typo'd or truncated UUID; an account closed at Mercury after you cached its ID; a base_url with a typo changing the effective path.

Common situations: Cached/stale account IDs synced earlier and the account was later closed; ID truncated by a CSV import or manual entry; copy/paste of an internal ID from Mercury's web dashboard that is not the API account UUID; trailing newline in the stored ID (partially mitigated by ERB::Util.url_encode, which will encode it into a non-matching path).

Related errors


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