Skip to content

Commit 7854f58

Browse files
committed
Register new installation-id-not-registered Error Code
1 parent 2316fde commit 7854f58

5 files changed

Lines changed: 52 additions & 5 deletions

File tree

src/messaging/messaging-errors-internal.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,22 @@ export function createFirebaseError(err: RequestResponseError): FirebaseMessagin
2929
if (err.response.isJson()) {
3030
// For JSON responses, map the server response to a client-side error.
3131
const json = err.response.data;
32-
const errorCode = getErrorCode(json);
32+
let errorCode = getErrorCode(json);
3333
const errorMessage = getErrorMessage(json);
34+
if (errorCode === 'UNREGISTERED' || errorCode === 'NOT_FOUND') {
35+
let requestData = err.response.config && err.response.config.data;
36+
if (typeof requestData === 'string') {
37+
try {
38+
requestData = JSON.parse(requestData);
39+
} catch (e) {
40+
// Ignore parsing errors.
41+
}
42+
}
43+
const messageObj = requestData && requestData.message;
44+
if (messageObj && typeof messageObj.fid === 'string') {
45+
errorCode = 'UNREGISTERED_FID';
46+
}
47+
}
3448
return FirebaseMessagingError.fromServerError(errorCode, errorMessage, json);
3549
}
3650

src/utils/api-request.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ export interface RequestResponse {
7575
readonly data?: any;
7676
/** For multipart responses, the payloads of individual parts. */
7777
readonly multipart?: Buffer[];
78+
/** Optional request config used to send this request. */
79+
readonly config?: any;
7880
/**
7981
* Indicates if the response content is JSON-formatted or not. If true, data field can be used
8082
* to retrieve the content as a parsed JSON object.
@@ -127,6 +129,7 @@ class DefaultRequestResponse implements RequestResponse {
127129
public readonly status: number;
128130
public readonly headers: any;
129131
public readonly text?: string;
132+
public readonly config?: RequestConfig;
130133

131134
private readonly parsedData: any;
132135
private readonly parseError: Error;
@@ -139,6 +142,7 @@ class DefaultRequestResponse implements RequestResponse {
139142
this.status = resp.status;
140143
this.headers = resp.headers;
141144
this.text = resp.data;
145+
this.config = resp.config;
142146
try {
143147
if (!resp.data) {
144148
throw new FirebaseAppError(AppErrorCodes.INTERNAL_ERROR, 'HTTP response missing data.');
@@ -177,11 +181,13 @@ class MultipartRequestResponse implements RequestResponse {
177181
public readonly status: number;
178182
public readonly headers: any;
179183
public readonly multipart?: Buffer[];
184+
public readonly config?: any;
180185

181186
constructor(resp: LowLevelResponse) {
182187
this.status = resp.status;
183188
this.headers = resp.headers;
184189
this.multipart = resp.multipart;
190+
this.config = resp.config;
185191
}
186192

187193
get text(): string {

src/utils/error.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,12 @@ export class MessagingClientErrorCode {
857857
'token can be unregistered for a variety of reasons. See the error documentation for more ' +
858858
'details. Remove this registration token and stop using it to send messages.',
859859
};
860+
public static INSTALLATION_ID_NOT_REGISTERED = {
861+
code: 'installation-id-not-registered',
862+
message: 'The provided installation ID is not registered. A previously valid installation ' +
863+
'ID can be unregistered for a variety of reasons. See the error documentation for more ' +
864+
'details. Remove this installation ID and stop using it to send messages.',
865+
};
860866
public static MISMATCHED_CREDENTIAL = {
861867
code: 'mismatched-credential',
862868
message: 'The credential used to authenticate this SDK does not have permission to send ' +
@@ -1130,6 +1136,7 @@ const MESSAGING_SERVER_TO_CLIENT_CODE: ServerToClientCode = {
11301136
THIRD_PARTY_AUTH_ERROR: 'THIRD_PARTY_AUTH_ERROR',
11311137
UNAVAILABLE: 'SERVER_UNAVAILABLE',
11321138
UNREGISTERED: 'REGISTRATION_TOKEN_NOT_REGISTERED',
1139+
UNREGISTERED_FID: 'INSTALLATION_ID_NOT_REGISTERED',
11331140
UNSPECIFIED_ERROR: 'UNKNOWN_ERROR',
11341141
};
11351142

test/integration/messaging.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ describe('admin.messaging', () => {
9797
});
9898
});
9999

100-
it('send(message with fid, dryRun) fails with registration-token-not-registered', () => {
100+
it('send(message with fid, dryRun) fails with installation-id-not-registered', () => {
101101
return getMessaging().send(fidMessage, true)
102-
.should.eventually.be.rejected.and.have.property('code', 'messaging/registration-token-not-registered');
102+
.should.eventually.be.rejected.and.have.property('code', 'messaging/installation-id-not-registered');
103103
});
104104

105105
it('sendEach()', () => {
@@ -166,7 +166,7 @@ describe('admin.messaging', () => {
166166
response.responses.forEach((resp) => {
167167
expect(resp.success).to.be.false;
168168
expect(resp.messageId).to.be.undefined;
169-
expect(resp.error).to.have.property('code', 'messaging/registration-token-not-registered');
169+
expect(resp.error).to.have.property('code', 'messaging/installation-id-not-registered');
170170
});
171171
});
172172
});
@@ -192,7 +192,7 @@ describe('admin.messaging', () => {
192192
expect(response.responses[1].messageId).to.be.undefined;
193193
expect(response.responses[1].error).to.have.property(
194194
'code',
195-
'messaging/registration-token-not-registered',
195+
'messaging/installation-id-not-registered',
196196
);
197197
});
198198
});

test/unit/messaging/messaging.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,26 @@ describe('Messaging', () => {
425425
.and.have.property('code', 'messaging/registration-token-not-registered');
426426
});
427427

428+
it('should fail when the backend server returns a detailed error for a FID target', () => {
429+
const resp = {
430+
error: {
431+
status: 'NOT_FOUND',
432+
message: 'test error message',
433+
details: [
434+
{
435+
'@type': 'type.googleapis.com/google.firebase.fcm.v1.FcmError',
436+
'errorCode': 'UNREGISTERED',
437+
},
438+
],
439+
},
440+
};
441+
mockedRequests.push(mockSendError(404, 'json', resp));
442+
return messaging.send(
443+
{ fid: 'mock-fid' },
444+
).should.eventually.be.rejectedWith('test error message')
445+
.and.have.property('code', 'messaging/installation-id-not-registered');
446+
});
447+
428448
['THIRD_PARTY_AUTH_ERROR', 'APNS_AUTH_ERROR'].forEach((errorCode) => {
429449
it(`should map ${errorCode} to third party auth error`, () => {
430450
const resp = {

0 commit comments

Comments
 (0)