title: Boto server error: Endpoint already exists with the same Token, but different attributes
body: <p>My app is returning the following error:</p>
  
  <blockquote>
    <p>BotoServerError: BotoServerError: 400 Bad Request
    {"Error":{"Code":"InvalidParameter","Message":"Invalid parameter: Token 
    Reason:
    Endpoint 
    [myendpoint] already exists with the same Token, but 
    different 
    attributes.","Type":"Sender"},"RequestId":"myrequestid"}</p>
  </blockquote>
  
  <p>I modelled my code on <a href="http://mobile.awsblog.com/post/Tx223MJB0XKV9RU/Mobile-token-management-with-Amazon-SNS" rel="nofollow">http://mobile.awsblog.com/post/Tx223MJB0XKV9RU/Mobile-token-management-with-Amazon-SNS</a> so as to avoid this kind of problem, but I can't work out what is causing this or how to fix it. It doesn't seem to matter whether I delete the endpoint from the SNS console, or set the endpointarn in my database to NULL, or both. Please help!</p>
  
  <pre><code>def createEndpoint(sns_conn, applicationArn, testUser, token):
      cpe_result = sns_conn.create_platform_endpoint(applicationArn, token, str(testUser.userid))
      try:
              endpointArn = cpe_result["CreatePlatformEndpointResponse"]["CreatePlatformEndpointResult"]["EndpointArn"]
      except BotoServerError, e:
              if "already exists with the same Token, but different attributes" in e.error_message:
                      s = e.error_message
                      endpointArn = s[s.index("Endpoint ") + len("Endpoint "):s.index("already exists") - 1]
              else:
                      raise
      testUser.endpointarn = endpointArn
      db.session.commit()
      return endpointArn
  
  def registerWithSNS(testUser):
      # Adaptation of code from http://mobile.awsblog.com/post/Tx223MJB0XKV9RU/Mobile-token-management-with-Amazon-SNS
      endpointArn = testUser.endpointarn
      token = request.form["token"]
      platform = request.form["platform"]
      updateNeeded = False
      createNeeded = endpointArn == None
  
      # Init sns_conn and applicationArn
      sns_conn = sns.connect_to_region("eu-west-1")
      lpa_response = sns_conn.list_platform_applications()
      platformApps = lpa_response["ListPlatformApplicationsResponse"]["ListPlatformApplicationsResult"]["PlatformApplications"]
      if platform == "Android":
              requiredSuffix = "GCM"
      elif platform == "iOS":
              requiredSuffix = "APNS"        
      else:
              raise Exception("Unknown platform: '{}'".format(platform))
      applicationArn = None
      for pa in platformApps:
              if pa["PlatformApplicationArn"].endswith(requiredSuffix):
                      applicationArn = pa["PlatformApplicationArn"]
                      break
      if applicationArn == None:
              raise Exception("Missing SNS platform application for '{}'".format(platform))
  
      if createNeeded:
              # No endpoint ARN is stored; need to call createEndpoint
              endpointArn = createEndpoint(sns_conn, applicationArn, testUser, token)
              createNeeded = False
  
      # Look up the endpoint and make sure the data in it is current, even if
      # it was just created
      try:
              gea_result = sns_conn.get_endpoint_attributes(endpointArn)
              returnedToken = gea_result["GetEndpointAttributesResponse"]["GetEndpointAttributesResult"]["Attributes"]["Token"]
              returnedEnabled = gea_result["GetEndpointAttributesResponse"]["GetEndpointAttributesResult"]["Attributes"]["Enabled"]
              updateNeeded = (returnedToken != token) or (returnedEnabled != "true")
      except BotoServerError, e:
              if e.error_code == "NotFound":
                      # we had a stored ARN, but the endpoint associated with it
                      # disappeared. Recreate it.
                      createNeeded = True
              else:
                      raise
  
      if createNeeded:
              createEndpoint(sns_conn, applicationArn, testUser, token)
  
      if updateNeeded:
              # endpoint is out of sync with the current data;
              # update the token and enable it.
              attribs = {}
              attribs["Token"] = token
              attribs["Enabled"] = "true"
              sns_conn.set_endpoint_attributes(endpointArn, attribs)
  </code></pre>