This error occurs when attempting to send a Firebase Cloud Messaging notification without properly specifying the recipient token, topic, or condition. The message cannot be delivered because FCM doesn't know where to send it.
The "messaging/invalid-recipient" error indicates that your FCM message request is missing a valid target recipient. Firebase Cloud Messaging requires every message to have exactly one of three targeting options: a device registration token, a topic name, or a condition expression. This error appears when none of these are provided, multiple are specified simultaneously, or the provided value is malformed. This error occurs at the message construction stage before attempting network delivery, meaning FCM rejected the message payload itself rather than encountering a problem with a specific device or network. It's a client-side validation error that prevents the message from entering FCM's delivery pipeline. The error typically appears in the SendResponse object when using Firebase Admin SDK methods like send(), sendAll(), or sendMulticast(). Unlike delivery errors that occur after the message is accepted, this error means the message was never valid enough to attempt delivery.
Check that your message object specifies one of: token, topic, or condition. Never specify multiple targeting methods:
// ✅ Correct - single token
const message = {
notification: {
title: 'Update',
body: 'New content available'
},
token: registrationToken // Must be defined and valid
};
// ✅ Correct - topic
const topicMessage = {
notification: { title: 'News', body: 'Breaking' },
topic: 'news-updates' // No /topics/ prefix needed here
};
// ❌ Wrong - no target
const badMessage = {
notification: { title: 'Test', body: 'Message' }
// Missing token, topic, or condition
};
// ❌ Wrong - multiple targets
const invalidMessage = {
notification: { title: 'Test', body: 'Message' },
token: someToken,
topic: 'news' // Cannot specify both
};Ensure the registration token from the client device is properly stored and retrieved:
// Add validation before sending
if (!registrationToken || registrationToken.trim() === '') {
console.error('Registration token is missing or empty');
throw new Error('Cannot send message: no valid token');
}
const message = {
notification: {
title: 'Your notification',
body: 'Notification content'
},
token: registrationToken
};
try {
const response = await admin.messaging().send(message);
console.log('Successfully sent:', response);
} catch (error) {
console.error('Error sending message:', error);
}Verify token storage in your database:
-- Check for null or empty tokens
SELECT user_id, fcm_token, updated_at
FROM user_devices
WHERE fcm_token IS NULL OR fcm_token = '';If sending to topics, ensure proper naming without the /topics/ prefix in the message object:
// ✅ Correct topic format
const message = {
notification: { title: 'Sports', body: 'Game update' },
topic: 'sports-news' // Use kebab-case, no prefix
};
// ❌ Wrong - includes prefix
const badTopicMessage = {
notification: { title: 'Sports', body: 'Update' },
topic: '/topics/sports-news' // Don't include /topics/
};
// Topic name rules:
// - Use only alphanumeric, dash, and underscore
// - No spaces or special characters
// - Max length: 900 characters
const validTopicPattern = /^[a-zA-Z0-9-_.~%]+$/;
if (!validTopicPattern.test(topicName)) {
throw new Error('Invalid topic name format');
}If using conditions for multi-topic targeting, verify the boolean expression is valid:
// ✅ Correct condition format
const message = {
notification: { title: 'Alert', body: 'Important update' },
condition: "'sports' in topics && 'news' in topics"
};
// ✅ Complex condition with OR
const complexCondition = "'ios' in topics || ('android' in topics && 'premium' in topics)";
// ❌ Wrong - malformed syntax
const badCondition = "sports AND news"; // Must use 'topic' in topics syntax
// Condition rules:
// - Use 'topicName' in topics for each topic
// - Combine with && (AND) or || (OR)
// - Use parentheses for precedence
// - Max 5 topics per conditionIsolate whether the issue is with message structure or token retrieval:
// Get a test token from your app (Firebase Admin SDK logs it at startup)
// or from FCM documentation sample
const TEST_TOKEN = 'dXXXXXXXXXX:APA91bXXXXXXXXXXXXXXXXXXXXXXXX';
const testMessage = {
notification: {
title: 'Test notification',
body: 'Testing message structure'
},
token: TEST_TOKEN
};
try {
const response = await admin.messaging().send(testMessage);
console.log('Message structure is valid');
// If this works, your token retrieval is the problem
} catch (error) {
console.error('Message structure issue:', error.code);
// If this fails, check your message object construction
}When using sendMulticast() or sendAll(), the targeting method must be in the individual message objects within the array, not at the top level. Each message in the batch must independently specify its token, topic, or condition.
For sendMulticast() specifically, you provide a single tokens array separately from the message payload, but the underlying implementation still requires valid token values. An empty tokens array will trigger this error.
The error code may vary slightly across Firebase Admin SDK implementations (Node.js, Java, Python, etc.), but the underlying cause is the same. In Node.js it appears as "messaging/invalid-recipient", while Java may show MessagingErrorCode.INVALID_ARGUMENT.
If migrating from legacy FCM HTTP API to HTTP v1 API, note that the message structure changed significantly. The v1 API requires the recipient to be specified within the "message" object, whereas the legacy API used separate "to", "registration_ids", or "condition" fields at the root level. Verify you're using the correct structure for your API version.
During development, use Firebase Admin SDK's dryRun option to validate messages without actually sending them:
const response = await admin.messaging().send(message, true); // true = dry runThis catches invalid-recipient errors early without consuming your FCM quota.
messaging/UNSPECIFIED_ERROR: No additional information available
How to fix "messaging/UNSPECIFIED_ERROR: No additional information available" in Firebase Cloud Messaging
App Check: reCAPTCHA Score Too Low
App Check reCAPTCHA Score Too Low
storage/invalid-url: Invalid URL format for Cloud Storage reference
How to fix invalid URL format in Firebase Cloud Storage
auth/missing-uid: User ID identifier required
How to fix "auth/missing-uid: User ID identifier required" in Firebase
auth/invalid-argument: Invalid parameter passed to method
How to fix "auth/invalid-argument: Invalid parameter passed to method" in Firebase