Amazon SNS: already exists with the same Token, but different attributes エラーの原因

はじめに

GoLang で Amazon SNS のCreatePlatformEndpoint API を使って、プラットフォームエンドポイントを作成しようとした際に、以下のようなエラーに遭遇しました。今回は、そのエラーの原因と対処法について解説します。

"error": "operation error SNS: CreatePlatformEndpoint, https response error StatusCode: 400, RequestID: 31859cc5-5e31-5416-9df5-c3a9036654ee, InvalidParameter: Invalid parameter: Token Reason: Endpoint arn:aws:sns:ap-northeast-1:******:endpoint/GCM/******/830d456e-dbea-304f-a2af-e2e9e666cd70 already exists with the same Token, but different attributes."

エラーが示す通り、同じデバイストークンで異なる属性を持つエンドポイントが既に存在していると、このエラーが発生します。具体的な原因とその理解について、私が学んだことを書いておきます。

該当コード

アプリケーションでは、デバイストークンを使って SNS のエンドポイントを作成しようとしています。また、CustomUserData を使ってデバイストークンの所有者情報を登録しています。

func (s *SNSEndpointService) createEndpoint(ctx context.Context, user domain.UserMeta, deviceToken string) error {
    customUserData := formatUserKey(user)
    input := sns.CreatePlatformEndpointInput{
        PlatformApplicationArn: &s.platformApplicationArn,
        Token:                  &deviceToken,
        Attributes: map[string]string{
            "Enabled": "true",
        },
        CustomUserData: &customUserData,
    }

    _, err := s.client.CreatePlatformEndpoint(ctx, &input)
    return err
}

この実装では、デバイストークンを使って新しいエンドポイントを作成しようとしていますが、CustomUserDataに異なるデータが含まれている場合、上記のエラーが発生します。

背景

モバイル端末 1 台を複数のユーザーで共有しているため、同じデバイストークンでも、その時々で所有者が変わるケースがあります。そのため、CustomUserDataを更新する必要がありました。CreatePlatformEndpointメソッドを使ってエンドポイントを作成し、既存のエンドポイントがある場合は ARN を取得し、その ARN を使ってCustomUserDataを更新するつもりでした。

しかし、これがエラーの原因となりました。

エラーの原因

Amazon SNS のCreatePlatformEndpointは、デバイストークンが同じであっても、他の属性(例: CustomUserData)が異なると、既存のエンドポイントを返さずにエラーを返す仕様になっています。このことは、AWS の公式ブログでも確認できます。

If a PlatformEndpoint with the same token, but different attributes already exists, doesn’t create anything; also does not return anything but throws an exception.

参考リンク

同様の問題に関して、参考になる情報はこちらです。

Stack Overflow - How do I check whether a mobile device has already been registered?

関連記事