firebase-admin
Version:
Firebase admin SDK for Node.js
287 lines (286 loc) • 13.2 kB
JavaScript
/*! firebase-admin v14.0.0 */
;
/*!
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.FirebaseMessagingError = exports.messagingClientErrorCode = exports.MessagingErrorCode = void 0;
const error_1 = require("../utils/error");
const deep_copy_1 = require("../utils/deep-copy");
/**
* The constant mapping for valid Messaging client error codes.
*/
exports.MessagingErrorCode = {
INVALID_ARGUMENT: 'invalid-argument',
INVALID_RECIPIENT: 'invalid-recipient',
INVALID_PAYLOAD: 'invalid-payload',
INVALID_DATA_PAYLOAD_KEY: 'invalid-data-payload-key',
PAYLOAD_SIZE_LIMIT_EXCEEDED: 'payload-size-limit-exceeded',
INVALID_OPTIONS: 'invalid-options',
INVALID_REGISTRATION_TOKEN: 'invalid-registration-token',
REGISTRATION_TOKEN_NOT_REGISTERED: 'registration-token-not-registered',
MISMATCHED_CREDENTIAL: 'mismatched-credential',
INVALID_PACKAGE_NAME: 'invalid-package-name',
DEVICE_MESSAGE_RATE_EXCEEDED: 'device-message-rate-exceeded',
TOPICS_MESSAGE_RATE_EXCEEDED: 'topics-message-rate-exceeded',
TOPICS_SUBSCRIPTION_RATE_EXCEEDED: 'topics-subscription-rate-exceeded',
MESSAGE_RATE_EXCEEDED: 'message-rate-exceeded',
THIRD_PARTY_AUTH_ERROR: 'third-party-auth-error',
TOO_MANY_TOPICS: 'too-many-topics',
AUTHENTICATION_ERROR: 'authentication-error',
SERVER_UNAVAILABLE: 'server-unavailable',
INTERNAL_ERROR: 'internal-error',
UNKNOWN_ERROR: 'unknown-error',
};
/**
* Internal Messaging client error code mapping used to construct ErrorInfo.
*/
exports.messagingClientErrorCode = {
INVALID_ARGUMENT: {
code: exports.MessagingErrorCode.INVALID_ARGUMENT,
message: 'Invalid argument provided.',
},
INVALID_RECIPIENT: {
code: exports.MessagingErrorCode.INVALID_RECIPIENT,
message: 'Invalid message recipient provided.',
},
INVALID_PAYLOAD: {
code: exports.MessagingErrorCode.INVALID_PAYLOAD,
message: 'Invalid message payload provided.',
},
INVALID_DATA_PAYLOAD_KEY: {
code: exports.MessagingErrorCode.INVALID_DATA_PAYLOAD_KEY,
message: 'The data message payload contains an invalid key. See the reference ' +
'documentation for the DataMessagePayload type for restricted keys.',
},
PAYLOAD_SIZE_LIMIT_EXCEEDED: {
code: exports.MessagingErrorCode.PAYLOAD_SIZE_LIMIT_EXCEEDED,
message: 'The provided message payload exceeds the FCM size limits. See the ' +
'error documentation for more details.',
},
INVALID_OPTIONS: {
code: exports.MessagingErrorCode.INVALID_OPTIONS,
message: 'Invalid message options provided.',
},
INVALID_REGISTRATION_TOKEN: {
code: exports.MessagingErrorCode.INVALID_REGISTRATION_TOKEN,
message: 'Invalid registration token provided. Make sure it matches the ' +
'registration token the client app receives from registering with FCM.',
},
REGISTRATION_TOKEN_NOT_REGISTERED: {
code: exports.MessagingErrorCode.REGISTRATION_TOKEN_NOT_REGISTERED,
message: 'The provided registration token is not registered. A ' +
'previously valid registration token can be unregistered for a variety of reasons. See the ' +
'error documentation for more details. Remove this registration token and stop using it to ' +
'send messages.',
},
MISMATCHED_CREDENTIAL: {
code: exports.MessagingErrorCode.MISMATCHED_CREDENTIAL,
message: 'The credential used to authenticate this SDK does not have permission ' +
'to send messages to the device corresponding to the provided registration token. Make sure the ' +
'credential and registration token both belong to the same Firebase project.',
},
INVALID_PACKAGE_NAME: {
code: exports.MessagingErrorCode.INVALID_PACKAGE_NAME,
message: 'The message was addressed to a registration token whose package name does ' +
'not match the provided "restrictedPackageName" option.',
},
DEVICE_MESSAGE_RATE_EXCEEDED: {
code: exports.MessagingErrorCode.DEVICE_MESSAGE_RATE_EXCEEDED,
message: 'The rate of messages to a particular device is too high. Reduce ' +
'the number of messages sent to this device and do not immediately retry sending to this device.',
},
TOPICS_MESSAGE_RATE_EXCEEDED: {
code: exports.MessagingErrorCode.TOPICS_MESSAGE_RATE_EXCEEDED,
message: 'The rate of messages to subscribers to a particular topic is too ' +
'high. Reduce the number of messages sent for this topic, and do not immediately retry sending ' +
'to this topic.',
},
TOPICS_SUBSCRIPTION_RATE_EXCEEDED: {
code: exports.MessagingErrorCode.TOPICS_SUBSCRIPTION_RATE_EXCEEDED,
message: 'The rate of subscription management requests to a particular topic is too ' +
'high. Reduce the number of requests sent for this topic, and do not immediately retry the ' +
'request.',
},
MESSAGE_RATE_EXCEEDED: {
code: exports.MessagingErrorCode.MESSAGE_RATE_EXCEEDED,
message: 'Sending limit exceeded for the message target.',
},
THIRD_PARTY_AUTH_ERROR: {
code: exports.MessagingErrorCode.THIRD_PARTY_AUTH_ERROR,
message: 'A message targeted to an iOS device could not be sent because the ' +
'required APNs SSL certificate was not uploaded or has expired. Check the validity of your ' +
'development and production certificates.',
},
TOO_MANY_TOPICS: {
code: exports.MessagingErrorCode.TOO_MANY_TOPICS,
message: 'The maximum number of topics the provided registration token can be ' +
'subscribed to has been exceeded.',
},
AUTHENTICATION_ERROR: {
code: exports.MessagingErrorCode.AUTHENTICATION_ERROR,
message: 'An error occurred when trying to authenticate to the FCM servers. Make ' +
'sure the credential used to authenticate this SDK has the proper permissions. See ' +
'https://firebase.google.com/docs/admin/setup for setup instructions.',
},
SERVER_UNAVAILABLE: {
code: exports.MessagingErrorCode.SERVER_UNAVAILABLE,
message: 'The FCM server could not process the request in time. See the error ' +
'documentation for more details.',
},
INTERNAL_ERROR: {
code: exports.MessagingErrorCode.INTERNAL_ERROR,
message: 'An internal error has occurred. Please retry the request.',
},
UNKNOWN_ERROR: {
code: exports.MessagingErrorCode.UNKNOWN_ERROR,
message: 'An unknown server error was returned.',
},
};
/** @const {Record<string, keyof typeof MessagingErrorCode>} Messaging server to client enum error codes. */
const MESSAGING_SERVER_TO_CLIENT_CODE = {
/* GENERIC ERRORS */
// Generic invalid message parameter provided.
InvalidParameters: 'INVALID_ARGUMENT',
// Mismatched sender ID.
MismatchSenderId: 'MISMATCHED_CREDENTIAL',
// FCM server unavailable.
Unavailable: 'SERVER_UNAVAILABLE',
// FCM server internal error.
InternalServerError: 'INTERNAL_ERROR',
/* SEND ERRORS */
// Invalid registration token format.
InvalidRegistration: 'INVALID_REGISTRATION_TOKEN',
// Registration token is not registered.
NotRegistered: 'REGISTRATION_TOKEN_NOT_REGISTERED',
// Registration token does not match restricted package name.
InvalidPackageName: 'INVALID_PACKAGE_NAME',
// Message payload size limit exceeded.
MessageTooBig: 'PAYLOAD_SIZE_LIMIT_EXCEEDED',
// Invalid key in the data message payload.
InvalidDataKey: 'INVALID_DATA_PAYLOAD_KEY',
// Invalid time to live option.
InvalidTtl: 'INVALID_OPTIONS',
// Device message rate exceeded.
DeviceMessageRateExceeded: 'DEVICE_MESSAGE_RATE_EXCEEDED',
// Topics message rate exceeded.
TopicsMessageRateExceeded: 'TOPICS_MESSAGE_RATE_EXCEEDED',
// Invalid APNs credentials.
InvalidApnsCredential: 'THIRD_PARTY_AUTH_ERROR',
/* FCM v1 canonical error codes */
NOT_FOUND: 'REGISTRATION_TOKEN_NOT_REGISTERED',
PERMISSION_DENIED: 'MISMATCHED_CREDENTIAL',
RESOURCE_EXHAUSTED: 'MESSAGE_RATE_EXCEEDED',
UNAUTHENTICATED: 'THIRD_PARTY_AUTH_ERROR',
/* FCM v1 new error codes */
APNS_AUTH_ERROR: 'THIRD_PARTY_AUTH_ERROR',
INTERNAL: 'INTERNAL_ERROR',
INVALID_ARGUMENT: 'INVALID_ARGUMENT',
QUOTA_EXCEEDED: 'MESSAGE_RATE_EXCEEDED',
SENDER_ID_MISMATCH: 'MISMATCHED_CREDENTIAL',
THIRD_PARTY_AUTH_ERROR: 'THIRD_PARTY_AUTH_ERROR',
UNAVAILABLE: 'SERVER_UNAVAILABLE',
UNREGISTERED: 'REGISTRATION_TOKEN_NOT_REGISTERED',
UNSPECIFIED_ERROR: 'UNKNOWN_ERROR',
};
/**
* @const {Record<string, keyof typeof MessagingErrorCode>} Topic management (IID)
* server to client enum error codes.
*/
const TOPIC_MGT_SERVER_TO_CLIENT_CODE = {
/* TOPIC SUBSCRIPTION MANAGEMENT ERRORS */
NOT_FOUND: 'REGISTRATION_TOKEN_NOT_REGISTERED',
INVALID_ARGUMENT: 'INVALID_REGISTRATION_TOKEN',
TOO_MANY_TOPICS: 'TOO_MANY_TOPICS',
RESOURCE_EXHAUSTED: 'TOPICS_SUBSCRIPTION_RATE_EXCEEDED',
PERMISSION_DENIED: 'AUTHENTICATION_ERROR',
DEADLINE_EXCEEDED: 'SERVER_UNAVAILABLE',
INTERNAL: 'INTERNAL_ERROR',
UNKNOWN: 'UNKNOWN_ERROR',
};
/**
* Firebase Messaging error code structure. This extends `FirebaseError`.
*/
class FirebaseMessagingError extends error_1.FirebaseError {
/**
* Creates the developer-facing error corresponding to the backend error code.
*
* @param serverErrorCode - The server error code.
* @param [message] The error message. The default message is used
* if not provided.
* @param [serverError] The error's raw server response.
* @returns The corresponding developer-facing error.
* @internal
*/
static fromServerError(serverErrorCode, message, serverError) {
// If not found, default to unknown error.
let clientCodeKey = 'UNKNOWN_ERROR';
if (serverErrorCode && serverErrorCode in MESSAGING_SERVER_TO_CLIENT_CODE) {
clientCodeKey = MESSAGING_SERVER_TO_CLIENT_CODE[serverErrorCode];
}
const error = (0, deep_copy_1.deepCopy)(exports.messagingClientErrorCode[clientCodeKey]);
error.message = message || error.message;
const rawData = serverError?.response?.data;
if (clientCodeKey === 'UNKNOWN_ERROR' && typeof rawData !== 'undefined') {
try {
error.message += ` Raw server response: "${typeof rawData === 'string' ? rawData : JSON.stringify(rawData)}"`;
}
catch (e) {
// Ignore JSON parsing error.
}
}
error.cause = serverError;
error.httpResponse = serverError?.response ? (0, error_1.toHttpResponse)(serverError.response) : undefined;
return new FirebaseMessagingError(error);
}
/**
* @internal
*/
static fromTopicManagementServerError(serverErrorCode, message, serverError) {
// If not found, default to unknown error.
const clientCodeKey = TOPIC_MGT_SERVER_TO_CLIENT_CODE[serverErrorCode] || 'UNKNOWN_ERROR';
const error = (0, deep_copy_1.deepCopy)(exports.messagingClientErrorCode[clientCodeKey]);
error.message = message || error.message;
const rawData = serverError?.response?.data;
if (clientCodeKey === 'UNKNOWN_ERROR' && typeof rawData !== 'undefined') {
try {
error.message += ` Raw server response: "${typeof rawData === 'string' ? rawData : JSON.stringify(rawData)}"`;
}
catch (e) {
// Ignore JSON parsing error.
}
}
error.cause = serverError;
error.httpResponse = serverError?.response ? (0, error_1.toHttpResponse)(serverError.response) : undefined;
return new FirebaseMessagingError(error);
}
/**
*
* @param info - The error code info.
* @param message - The error message. This will override the default message if provided.
*/
constructor(info, message) {
// Override default message if custom message provided.
super({
code: `messaging/${info.code}`,
message: message || info.message,
httpResponse: info.httpResponse,
cause: info.cause,
});
/** @internal */
this.codePrefix = 'messaging';
}
}
exports.FirebaseMessagingError = FirebaseMessagingError;