添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Hello people!

I'm doing some requests to the Contacts endpoint to get all of my contacts. But, sometimes I get an error that I can't handle. I think that the server isn't responding to my request.

There are a lot of contacts (700k) and I'm running the code below in a for iteration.

I know about the rate limits, and I'm sure I'm not passing thru.

url = 'https://api.hubapi.com/crm/v3/objects/contacts'
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + <token>
params = {
'limit': 100,
'properties': <list of properties>,
'after': <next_paging number>
response = requests.get(url=url, headers=headers, params=params)

Sometimes I get the error below, sometimes I don't.

('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
http.client.RemoteDisconnected: Remote end closed connection without response
urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

I've summarized the error so it doesn't get too big.

Can anyone help me, please?

Hey there,

Founder at Stacksync here. RemoteDisconnected is a common HubSpot error that can happen for a variety of reasons, coming due to HubSpot issues (most often) or sometimes network issues depending on how reliable is your cloud provider and network tier.

At Stacksync, we have several parallel data read/write processed for a single HubSpot instance. We have implemented a retry module on the API call with exponential backoff delays. It ensures that you do not exceed rate limits, as well as being robust to repeated RemoteDisconnected errors (the error can happen sometimes 1-4 times in a row, and this can lead to coordination issues between processes if you parallellize queries).

For context, Stacksync powers real-time and bidirectional sync between HubSpot and Databases like Postgres, Snowflake, BigQuery, MySQL and more.

Hi @RubenB ,

Thank you for your response about the RemoteDisconnected error in HubSpot. I appreciate the information on how Stacksync handles parallel data processing and the retry module. It’s very helpful for improving my script. I have a few quick questions:

  1. Can you share more details about how you implemented the retry module? Any best practices or specific libraries you recommend?
  2. Could you provide examples of how you manage rate limits effectively in a high-volume environment?

I look forward to using these strategies in my setup.

Thanks again!
Gerald

I'm encountering the same issue today:

ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

Even after using the provided sample from here: https ://github .com /HubSpot /sample -apps -retry -middleware /blob /main /python /cli .py , the error persists, particularly with status 429 or "RemoteDisconnected."

Here’s my code:

from urllib3.util import Retry
from requests.adapters import HTTPAdapter
import requests
from hubspot import HubSpot
# Create a HubSpot client with retry logic
def create_client(api_key):
    # Set interval based on environment
    if environment == "sb":  # Sandbox
        interval = 6  # 6 seconds for free plan
    else:  # Production
        interval = 1  # 1 second for pro plan
    # Define the retry strategy
    retry_strategy = Retry(
        total=5,  # Total number of retries
        backoff_factor=interval,  # Exponential backoff
        status_forcelist=[429, 500, 502, 504],  # Status codes to retry
        allowed_methods=["HEAD", "GET", "OPTIONS", "POST", "PUT"],  # Methods for retry
        raise_on_status=False  # Don't raise error after final retry
    # Create an HTTP adapter with the retry strategy
    adapter = HTTPAdapter(max_retries=retry_strategy)
    # Create a session and mount the adapter
    http = requests.Session()
    http.mount("https://", adapter)
    http.mount("http://", adapter)
    # Update session headers with API token
    http.headers.update(
        {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}
    return HubSpot(access_token=api_key, http=http)
# Create HubSpot API clients for different calls
api_client_companies = create_client(get_access_token("HUBSPOT_COMPANIES", "companies"))
api_client_contacts = create_client(get_access_token("HUBSPOT_CONTACTS", "contacts"))


Could anyone share insights or suggest further improvements? Thank you!

Hi @dennisedson !

Thanks for reply! It's not a python bug. It's about the non-response of some messages by Hubspot's API server.

I made some improvements in the API request in the python script. I configured the retry factor from the urllib3 library ( https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html#module-urllib3.util.retry ) and now my pipeline it's not crashing anymore.

But, even so, I would like to know why the Hubspot API server is not answer some of my requests...

Thanks in advance.

//START END-USER CONFIGURATION //------------------------------ //selectors for hover card triggers var allHoverCardTriggers = '.author-name-link,.friend-list .friend a,.username a,.avatar,.user-avatar,.author-img, .authors a, .messageauthorusername a, a.lia-user-name-link, .js-latest-post-by-from a, .user-online-list li a, a.UserAvatar, .customUsersOnline a, #authors a,.dashboard-followers a.user-name, .dashboard-following a.user-name,.author-login-wrapper a, .hb-leaderboard a, .author-img-floated'; // Forward calling page's URL params to endpoint URL as well, helps with testing! var params = (new URL(location.href)).searchParams; var userApiUrl = '/plugins/custom/hubspot/hubspot/hovercardendpoint?' + ((params.set('user_id', '') == []._) && params.toString()); if($('.hover-card-container').length<1){ $('body').append('
'); var cardWrapper = $('.hover-card-container'); var error = false; var thisUserID = ''; var thisUserLogin = ''; var userLink =''; var cardTimer; var leaveTimer; function mouseenter(Elem) { var thisEl = Elem; cardTimer = setTimeout(function(){ var docWidth = $(document).width(); var rightSide = false; var userLink = thisEl.attr('href'); if($('.ViewProfilePage').length && $('img.lia-user-avatar-profile',thisEl).length){thisUserID = '';} else if(thisEl.attr('href')=='#' || thisEl.attr('href')=='' || !userLink.match('viewprofilepage')){ return false;} else{ var thisLen = (userLink).split('/'); thisUserID = (thisLen)[thisLen.length-1]; var thisCard = $('.profileCard[data-user='+thisUserID+']',cardWrapper); var cardId = 'userProfileCard-'+ thisUserID; var addAttr = thisEl.attr('aria-describedby',cardId); var thisElTopOffset = Math.round(thisEl.offset().top+(thisEl.height()/2)+30); var thisElbottomoffset = "auto"; var className = ""; var winHeight = $(window).height(); var elOffset = thisEl.offset(); var scrollTop = $(window).scrollTop(); var elementOffset = thisEl.offset().top; var distanceTop = (elementOffset - scrollTop); var distanceBottom = (winHeight + scrollTop) - (elOffset.top + thisEl.outerHeight(true)); var distanceLeft = Math.round(thisEl.offset().left); var bodyHight = $('body').height(); var topParam = ''; var bottomparam = ''; var position = ''; var className = 'topArrow'; cardId if(distanceBottom < 300 ){ if(distanceLeft < 59){ thisCard.removeClass('bottomArrow'); var className = 'leftArrow'; var distanceLeft = (distanceLeft)+(39); var thisElTopOffset = (thisElTopOffset)-(150); }else{ var thisElTopOffset = (thisElTopOffset)-(301); var className = 'bottomArrow'; thisCard.removeClass('topArrow'); thisCard.removeClass('leftArrow'); var distanceLeft = (distanceLeft)-(45); else{ if(distanceLeft < 59){ thisCard.removeClass('topArrow'); var className = 'leftArrow'; var distanceLeft = (distanceLeft)+(39); var thisElTopOffset = (thisElTopOffset)-(150); }else{ thisCard.removeClass('leftArrow'); thisCard.removeClass('bottomArrow').addClass('topArrow'); var distanceLeft = (distanceLeft)-(45); if(thisCard.length && $('.profileCard[data-user='+thisUserID+'] .preloader',cardWrapper).length<1){ $('.profileCard',cardWrapper).hide(); thisCard.addClass(className); rightSide?thisCard.addClass('rightArrow'):thisCard.removeClass('rightArrow'); thisCard.delay(0).css({'top':(thisElTopOffset),'left':distanceLeft,'bottom':thisElbottomoffset}).fadeIn(); } else { var ajaxReturn = ''; //just in case thisCard.remove(); //hover card wrapper markup var rightArrowClass = rightSide?'rightArrow':''; if(thisElTopOffset != "auto"){ topParam = 'px'; if(thisElbottomoffset != "auto"){ bottomparam = 'px'; var profileCardHtml = '