instructure/canvas-lms · error · FailedSnsInteraction
Unable to create or reassign SNS endpoint for access_token #
Error message
Unable to create or reassign SNS endpoint for access_token #{access_token.global_id} What it means
NotificationEndpoint#create_platform_endpoint manages AWS SNS platform endpoints for push-notification access tokens. If SNS creation/assignment keeps failing and the code has already retried once (retried == true), it raises FailedSnsInteraction with this message including the access token's global id. It means Canvas could not create or reassign the SNS endpoint after the documented retry.
Solutions
- Check AWS credentials and IAM policy for the SNS actions used (CreatePlatformEndpoint, CreatePlatformApplication, SetEndpointAttributes) in the configured region.
- Verify the SNS platform application ARN configured for the account is valid and exists in the current region.
- Inspect the underlying exception (logged via Canvas::Errors.capture_exception) to see the exact AWS error, e.g. invalid device token — re-register the device to get a fresh token.
- Delete stale NotificationEndpoint/AccessToken rows and let the client re-register push notifications.
- Check for AWS throttling or SNS outages if the failure is intermittent.
Example fix
// before
# relies on implicit retry; fails with FailedSnsInteraction after 1 retry
NotificationEndpoint.create_or_update(access_token, token: device_token)
// after
begin
NotificationEndpoint.create_or_update(access_token, token: device_token)
rescue FailedSnsInteraction => e
Rails.logger.warn("SNS endpoint failed for token #{access_token.global_id}: #{e.cause&.message}")
access_token.notification_endpoints.destroy_all # clear stale endpoint, allow re-register
raise
end Defensive patterns
Strategy: retry
Validate before calling
return unless access_token.present? && device_token.present? return unless Aws.config[:region] == ENV['SNS_REGION']
Try / catch
begin NotificationEndpoint.create_or_update(access_token, token: device_token) rescue FailedSnsInteraction => e Canvas::Errors.capture_exception(:push_notifications, e, :error) # surface a re-register flow to the mobile client end
Prevention
- Validate SNS credentials, region, and platform application ARN at deploy time
- Request fresh device tokens from clients when SNS reports InvalidParameter
- Grant IAM sns:CreatePlatformEndpoint and related actions to the app role
- Monitor the captured cause exception for recurring AWS error codes
When it happens
Trigger: Registering a mobile push endpoint when AWS SNS repeatedly fails (invalid device token, IAM permissions missing sns:CreatePlatformEndpoint/sns:CreatePlatformApplication, wrong platform application ARN) so the first retry also fails and retried is already true.
Common situations: Misconfigured SNS credentials/region or expired AWS keys in the environment; stale/invalid APNs or FCM device tokens; deleted or recreated SNS platform application leaving tokens orphaned; AWS throttling/region mismatch.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- No region specified for: #
- A new_id, '# ', referenced an existing # and the # with #…
- A new_integration_id, '#
- A student referenced a non-existent user #
- A user did not pass validation
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/286cdc4f282a9f25.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/notification_endpoint.rb:110
self.arn = $1
# steal the endpoint by setting the access token
endpoint_updated = false
begin
sns_client.set_endpoint_attributes(
endpoint_arn: arn,
attributes: { "CustomUserData" => access_token.global_id.to_s }
)
endpoint_updated = true
rescue Aws::SNS::Errors::NotFound => ex
# there's a race condition if the endpoint we JUST found
# and are trying to update gets deleted by a different
# request in the same moment. In this case we should
# try to create again, since the blocking endpoint is gone,
# but only once since if it's cyclical something strange
# is happening.
endpoint_updated = false
if retried
raise FailedSnsInteraction, "Unable to create or reassign SNS endpoint for access_token #{access_token.global_id}"
end
retried = true
Canvas::Errors.capture_exception(:push_notifications, ex, :info)
end
retry unless endpoint_updated
end
end
def delete_platform_endpoint
return unless endpoint_exists? && own_endpoint?
sns_client.delete_endpoint(endpoint_arn: arn)
end
end
View on GitHub (pinned to 1c9f0bb801)