Closed victoravr closed 4 months ago
Hello, @victoravr and thank you for opening this issue. Can you confirm if you also see this happen when you set optOut
to ALL
as well? Also, are you calling initializePushNotifications()
before your identifyUser()
call?
This does seem to be a bug and we'll investigate this as such. The address should not be required per Pinpoint's documentation.
Hi @victoravr. As @cwomack mentioned, we are currently treating this as a bug, however I am unable to reproduce the error via the steps below:
identifyUser
with optOut: 'ALL'
identifyUser
with optOut: 'NONE'
Could you please share more of your use case with us so we can better reproduce the circumstances around which you are seeing the issue? It would also be helpful if you could use Flipper or something similar to inspect the actual network calls being made? In particular - we want to be sure that the endpointId of the calls are consistent between calls E.g.
// On app start, request is made automatically to
// https://pinpoint.<region>.amazonaws.com/v1/apps/123/endpoints/456
{
RequestId: "abc123",
...
Address: "my-token-string",
...
}
// On identifyUser call, request is made to (same endpoint)
// https://pinpoint.<region>.amazonaws.com/v1/apps/123/endpoints/456
{
RequestId: "xyz789",
...
OptOut: "ALL",
...
}
Hello, @victoravr and thank you for opening this issue. Can you confirm if you also see this happen when you set
optOut
toALL
as well? Also, are you callinginitializePushNotifications()
before youridentifyUser()
call?
Sorry, haven't tried setting optOut
to ALL
yet. Will try it soon (need to set it to ALL for the endpoint upon user sign-out I guess) and will report back.
And yes, initializePushNotifications() is called before identifyUser() call.
Hi @victoravr. As @cwomack mentioned, we are currently treating this as a bug, however I am unable to reproduce the error via the steps below:
- Start my RN app on iOS simulator
- Call
identifyUser
withoptOut: 'ALL'
- Call
identifyUser
withoptOut: 'NONE'
Could you please share more of your use case with us so we can better reproduce the circumstances around which you are seeing the issue? It would also be helpful if you could use Flipper or something similar to inspect the actual network calls being made? In particular - we want to be sure that the endpointId of the calls are consistent between calls E.g.
// On app start, request is made automatically to // https://pinpoint.<region>.amazonaws.com/v1/apps/123/endpoints/456 { RequestId: "abc123", ... Address: "my-token-string", ... }
// On identifyUser call, request is made to (same endpoint) // https://pinpoint.<region>.amazonaws.com/v1/apps/123/endpoints/456 { RequestId: "xyz789", ... OptOut: "ALL", ... }
Hmm, could you try to reproduce the error on the physical device, if possible? I have noticed this error while testing on iPhone Xr with iOS 17.4.1.
OK, I have updated identifyUser() call to set optOut to 'ALL' upon user sign-out.
During testing this time I can't reproduce the reported error - neither for 'NONE', nor for 'ALL' optOut without address.
If you can't reproduce it on the physical device too, happy to close this issue - maybe it was a bug in my code.
Thanks!
Appreciate the confirmation, @victoravr. We haven't been able to reproduce it on out side either following the documented flows. We'll close this issue out for now, but feel free to reply back if you happen to find a way to reproduce it reliably again!
Hi @cwomack and @cshfang,
Getting this error again! :( This time I've installed Reactotron for debugging. Here's API request:
RequestId:4fd0c28e-4af5-46dd-a795-aeb765af7cc2
EffectiveDate:2024-04-28T00:53:07.680Z
ChannelType:APNS_SANDBOX
Attributes:
AppVersion:ios/17.4
Make:null
Model:null
ModelVersion:17.4
Platform:ios
Location:
OptOut:NONE
UserId:c9ae5488-2001-70f4-13d8-24ff71a0ff45
And response: Message Missing Address
Is it a bug?
Hmm is this the first network call to Pinpoint being made by the application? When initializing push notifications, there should be a call made automatically to bootstrap the endpoint with the token (address).
Would it be possible to add a onTokenReceived handler to check if the token is being received? How early on is the initializePushNotifications call being made in the lifecycle of your application?
What is supposed to happen is:
initializePushNotifications
is called, listeners for all native events are wired up, flushing the aforementioned queueIt seems like somehow step 4 either did not trigger or did not complete in time 🤔 so it would be helpful to know if there are any other calls being made by the library at all..
Thanks for prompt reply, @cshfang!
Hmm is this the first network call to Pinpoint being made by the application? When initializing push notifications, there should be a call made automatically to bootstrap the endpoint with the token (address).
Yes, looks like it was the first network call to Pinpoint made by the app since launch.
Would it be possible to add a onTokenReceived handler to check if the token is being received? How early on is the initializePushNotifications call being made in the lifecycle of your application?
I've got onTokenReceived used inside useEffect of the React component, as below:
import React, {useEffect} from 'react';
import {
onTokenReceived,
OnTokenReceivedInput,
OnTokenReceivedOutput,
} from 'aws-amplify/push-notifications';
import {setDeviceToken} from './src/redux/deviceToken';
import {useDispatch} from 'react-redux';
export const RegisterToken = () : React.JSX.Element => {
const dispatch = useDispatch();
useEffect(() => {
const tokenReceivedHandler: OnTokenReceivedInput = token => {
// Do something with the received token
console.log(token, 'token');
dispatch(setDeviceToken(token));
};
const tokenListener: OnTokenReceivedOutput =
onTokenReceived(tokenReceivedHandler);
return () => {
tokenListener.remove();
};
}, []);
// @ts-ignore
return <></>;
};
then in App.tsx:
...
import {RegisterToken} from './RegisterToken';
...
// @ts-ignore
return (
<>
<Provider store={store}>
<PersistGate loading={<Text>Loading...</Text>} persistor={persistor}>
<QueryClientProvider client={queryClient}>
<SafeAreaProvider>
<ThemeProvider theme={theme}>
<RegisterToken />
<AppNavigation />
</ThemeProvider>
</SafeAreaProvider>
</QueryClientProvider>
</PersistGate>
</Provider>
<Toast />
</>
);
...
Is this approach supported?
Hey @victoravr.
Yes, looks like it was the first network call to Pinpoint made by the app since launch.
Is there a network call made afterwards?
Where in the application are you calling initializePushNotifications
and identifyUser
? It seems like perhaps the identifyUser
network call is happening between the endpoint has a chance to get the token registered. This ought not to happen and I'm hoping to better understand why it's happening in your application flow
After testing this out, I do think we have a potential race condition if initializePushNotifications
and identifyUser
are called closely in sequence due to the fact that they are both trying to update a Pinpoint endpoint behind the scenes. There are a couple issues here:
identifyUser
call to end up earlier in sequence than the one triggered by initializePushNotifications
depending on your application. As a result, if an endpoint is created/updated with OptOut
set to 'NONE'
before the address is set by initializePushNotifications
, you can run into the issue you're seeing above.Issue 2 is a bit hairier to resolve as it is not clear to me why the Pinpoint service does not allow the use case of opting an endpoint out before attaching an address to it. So I am in contact with the Pinpoint team regarding this. Pending their response, I will work on evaluating possible solutions to this.
In the meantime, since you are listening for a token, I think a potential fix in the meantime could be to pass that token in along with your identifyUser
call as the address.
Hi @cshfang,
Is there a network call made afterwards?
Yes, looks like there was a call after that with address:
{
"RequestId": "7d62b64a-bcca-48cd-872f-db17b3bcdca3",
"EffectiveDate": "2024-04-28T01:04:49.043Z",
"ChannelType": "APNS_SANDBOX",
"Address": "80042cfb1a57d0426ad71ebe50...663931ca806",
"Demographic": {
"AppVersion": "ios/17.4",
"Make": null,
"Model": null,
"ModelVersion": "17.4",
"Platform": "ios"
},
"Location": {},
"User": {
"UserId": "ap-southeast-2:7de8bcb7-b604-cd23-5116-5211a83a494f"
}
}
Where in the application are you calling
initializePushNotifications
andidentifyUser
? It seems like perhaps theidentifyUser
network call is happening between the endpoint has a chance to get the token registered. This ought not to happen and I'm hoping to better understand why it's happening in your application flow
I'm calling initializePushNotifications(); in root index.js after Amplify.configure(...); but before AppRegistry.registerComponent(appName, () => App);
As for identifyUser, it's inside useEffect in AppNavigation.js:
...
useEffect(() => {
if (user) {
if (user.userId) {
identifyUsertoPinpoint({
deviceToken: deviceToken,
userId: user.userId,
optOut: 'NONE'
});
};
};
}, [user, deviceToken]);
...
... useEffect(() => { if (user) { if (user.userId) { identifyUsertoPinpoint({ deviceToken: deviceToken, userId: user.userId, optOut: 'NONE' }); }; }; }, [user, deviceToken]); ...
I think the network call happening out of order is consistent with my findings. However, I noticed that you are already sending the device token along with your identifyUser call. I don't know what the exact body of your identifyUsertoPinpoint
function looks like - but two things we want to make sure of are:
identifyUser
call e.g. options: { address: deviceToken, optOut }
... make sure of are:
- That deviceToken is passed along with the
identifyUser
call e.g.options: { address: deviceToken, optOut }
- That the address is never explicitly an empty string (this might cause weirdness with the service API)
Thanks! Updated my code to only do API request with OptOut if deviceToken is not empty/null.
Question: when device token is sent to the end user device/simulator for APNs (e.g. in a Sandbox)?
At least on simulator, I've noticed it does not appear at all sometimes...
Question: when device token is sent to the end user device/simulator for APNs (e.g. in a Sandbox)?
At least on simulator, I've noticed it does not appear at all sometimes...
It should be invoked when didRegisterForRemoteNotificationsWithDeviceToken
is invoked in the AppDelegate - so essentially when an app is launched for the first time. On simulator the token is only reliably passed to the JS side after terminating the app, relaunching, and then doing an additional background + resume. It seems to be another quirk with the simulator at this time though.
Hi @victoravr
Amplify JS v6.3.1 has just been released. It should contain the following fixes: https://github.com/aws-amplify/amplify-js/pull/13319 https://github.com/aws-amplify/amplify-js/pull/13353
We believe these fixes should resolve your issue of the Missing Address
error being triggered by network race conditions which might result in an identifyUser
call attempting to create an endpoint with OptOut: 'NONE'
and no Address
. Could you please help us by verifying if this is indeed the case by updating to the latest Amplify version? Thank you
... Could you please help us by verifying if this is indeed the case by updating to the latest Amplify version?
Hi @cshfang ,
I've installed Amplify JS v6.3.1, and tested my app on a physical iPhone device.
Unfortunately, notifications did not work initially due to a token not being issued after launching the app.
I had to close the app, re-launch it, sign-in as AWS Cognito user, then minimize it and re-open - and only then APNs token had been issued... not sure why this is the case..
Any advise? Many thanks!
Hmm there should definitely be no reason for a need to sign in as a user as the endpoints are tied to device. Was the token not issued from a fresh install? We are responding to the didRegisterForRemoteNotificationsWithDeviceToken
callback from the native side so it's not quite clear why this might be happening.
Could you try to add NSLog to your AppDelegate to make sure that didRegisterForRemoteNotificationsWithDeviceToken
is being called but not propagating to the React Native side?
@victoravr Thanks for your patient on this stuff, by the way. Would you mind opening a separate ticket to track the token issue? Given that I have seen similar behavior on simulator with iOS 17, I am wondering if something changed in the bootstrapping behavior of the observers which fire the registration call in the native layer. It would be helpful if we could track the investigation of this on a ticket dedicated to that.
Before opening, please confirm:
JavaScript Framework
React Native
Amplify APIs
Push Notifications
Amplify Version
v6
Amplify Categories
notifications
Backend
CDK
Environment information
Describe the bug
Can't update optOut for AWS Pinpoint endpoint without address (APNs device token)
Expected behavior
Should be able to update optOut (e.g. set to 'NONE') for AWS Pinpoint endpoint without address (APNs device token)
Reproduction steps
call identifyUser() after user logs in. If no device token provided along with optOut option as address, console warning appears as in screenshot.
Code Snippet
Log output
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
iPhone 15 Pro + Simulator
Mobile Operating System
iOS 17.4
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots