we-promise/sure · error · ActiveRecord::RecordNotFound

record_not_found

record_not_found

Error message

The requested resource was not found

What it means

Raised by find_recurring_transaction in Api::V1::RecurringTransactionsController (app/controllers/api/v1/recurring_transactions_controller.rb:143-148). It fires when params[:id] fails the valid_uuid? guard or when the id is not inside the supplied scope (read_recurring_transactions_scope for show, write_recurring_transactions_scope for update/destroy). Both paths produce a 404 record_not_found.

Source

Thrown at app/controllers/api/v1/recurring_transactions_controller.rb:148

    Rails.logger.error e.backtrace.join("\n")

    render json: {
      error: "internal_server_error",
      message: "Internal server error"
    }, status: :internal_server_error
  end

  private
    def set_readable_recurring_transaction
      @recurring_transaction = find_recurring_transaction(read_recurring_transactions_scope)
    end

    def set_writable_recurring_transaction
      @recurring_transaction = find_recurring_transaction(write_recurring_transactions_scope)
    end

    def find_recurring_transaction(scope)
      raise ActiveRecord::RecordNotFound unless valid_uuid?(params[:id])

      scope.includes(:account, :merchant).find(params[:id])
    end

    def ensure_read_scope
      authorize_scope!(:read)
    end

    def ensure_write_scope
      authorize_scope!(:write)
    end

    def read_recurring_transactions_scope
      current_resource_owner.family.recurring_transactions.accessible_by(current_resource_owner)
    end

    def write_recurring_transactions_scope
      scope = current_resource_owner.family.recurring_transactions

View on GitHub (pinned to e69894adb9)

Solutions

  1. List with GET /api/v1/recurring_transactions and use an id from the response
  2. For PATCH/DELETE, confirm the underlying account is writable by the token owner (not a view-only shared account)
  3. Validate the id is a UUID before the call
  4. Verify the X-Api-Key family owns the transaction
Defensive patterns

Strategy: try-catch

Validate before calling

UUID_RE = /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i
UUID_RE.match?(rt_id) or raise ArgumentError, 'recurring_transaction id must be a UUID'

Try / catch

begin
  client.patch("/api/v1/recurring_transactions/#{id}", body)
rescue Faraday::ResourceNotFound
  # 404: id unknown, other family, or not WRITABLE by this owner (write scope)
end

Prevention

When it happens

Trigger: GET/PATCH/DELETE /api/v1/recurring_transactions/:id with a non-UUID id; another family's recurring transaction id; and importantly an id that is readable but not writable — update/destroy use the write scope, so a transaction on an account not writable_by the token owner 404s even though show succeeds.

Common situations: Read-only shared account scenarios (spouse's account shared view-only) where a PATCH works in the UI but 404s via API; id copied from a different family or environment; deleted recurring transaction.

Related errors


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