Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -701,17 +701,44 @@ export abstract class AWSWebSocketProvider {
});

let errorMessage = JSON.stringify(payload ?? data);
let isAuthError = false;

if (type === MESSAGE_TYPES.EVENT_SUBSCRIBE_ERROR) {
const { errors } = JSON.parse(String(message.data));
if (Array.isArray(errors) && errors.length > 0) {
const error = errors[0];
errorMessage = `${error.errorType}: ${error.message}`;
// Check if this is an authentication/authorization error
isAuthError =
error.errorType === 'UnauthorizedException' ||
error.errorType === 'Unauthorized';
}
}

// Also check for auth errors in the error message
isAuthError =
isAuthError ||
errorMessage.includes('UnauthorizedException') ||
errorMessage.includes('Unauthorized') ||
errorMessage.includes('Token expired') ||
errorMessage.includes('NotAuthorizedException') ||
errorMessage.includes('401') ||
errorMessage.includes('403');

this.logger.debug(`${CONTROL_MSG.CONNECTION_FAILED}: ${errorMessage}`);

// If it's an auth error, trigger reconnection to refresh tokens
if (isAuthError && this.awsRealTimeSocket) {
this.logger.debug(
'Subscription failed due to auth error, closing WebSocket to trigger reconnection with fresh tokens',
);
// Close the WebSocket connection which will trigger reconnection
// The connectionStateMonitor will detect the closed connection and since
// intendedConnectionState is still 'connected', it will trigger ConnectionDisrupted
// which causes the ReconnectionMonitor to reconnect with fresh tokens
this.awsRealTimeSocket.close(1000, 'Auth error - reconnecting');
}

observer.error({
errors: [
{
Expand Down
16 changes: 16 additions & 0 deletions packages/datastore/src/sync/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,22 @@ export class SyncEngine {
) {
this.datastoreConnectivity.socketDisconnected();
}
// Handle authentication errors that occur when tokens expire
// This fixes the issue where WebSocket subscriptions silently fail after token expiration
// See: https://github.com/aws-amplify/amplify-js/issues/12954
else if (
msg?.includes?.('No current user') ||
msg?.includes?.('Unauthorized') ||
msg?.includes?.('Token expired') ||
msg?.includes?.('NotAuthorizedException')
) {
logger.warn(
'DataStore sync subscription failed due to authentication error. Triggering reconnection...',
msg,
);
// Trigger socket disconnection to force a full reconnection with refreshed tokens
this.datastoreConnectivity.socketDisconnected();
}
};
}

Expand Down