Skip to content

Firebase Cloud Function (Gen 1) fails to send FCM notification with "Unknown server error" (returns HTML 404 Not Found) #9280

@florianheroux5-svg

Description

@florianheroux5-svg

Hello everyone,
I'm facing a persistent and strange issue with a Firebase Cloud Function (1st Gen) that is supposed to send a push notification when a new message is created in a Firestore chat.
The function triggers correctly, successfully reads all necessary data from Firestore (user tokens, etc.), but fails at the very last step: calling messaging.sendToDevice(). The function log shows an Error: An unknown server error was returned. Raw server response: "..." which contains a standard Google "404 Not Found" error page.
Here is the context and what I've tried so far.

  1. The Goal
    When a new document is created in privateLeagues/{leagueId}/messages/{messageId}, a push notification should be sent to all other members of that private league.
  2. The Cloud Function Code (functions/index.js)
    This is the 1st Gen function running on Node.js 20. The firebase-admin and firebase-functions versions are from our stable V1.
    code
    JavaScript
    // functions/index.js
    const functions = require("firebase-functions");
    const admin = require("firebase-admin");

admin.initializeApp();
const db = admin.firestore();
const messaging = admin.messaging();

exports.notifyOnNewChatMessage = functions.firestore
.document("privateLeagues/{leagueId}/messages/{messageId}")
.onCreate(async (snap, context) => {
const message = snap.data();
const { leagueId } = context.params;

try {
  const leagueDoc = await db.collection("privateLeagues").doc(leagueId).get();
  if (!leagueDoc.exists) {
    functions.logger.log("League not found.");
    return null;
  }

  const leagueData = leagueDoc.data();
  const members = leagueData.members.map(m => m.userId || m);

  const payload = {
    notification: {
      title: `New message in "${leagueData.name}"`,
      body: `${message.userName}: ${message.text.substring(0, 100)}`,
      icon: '/pwa-192x192.png',
    },
    data: {
      url: `https://vrai-ffp.web.app/ligues/${leagueId}/chat` // My production URL
    }
  };

  const tokensToNotify = [];
  for (const userId of members) {
    if (userId !== message.userId) {
      const tokensSnap = await db.collection("users").doc(userId).collection("notificationTokens").get();
      tokensSnap.forEach(tokenDoc => tokensToNotify.push(tokenDoc.id));
    }
  }

  if (tokensToNotify.length > 0) {
    functions.logger.log(`Attempting to send notification to ${tokensToNotify.length} token(s).`);
    return messaging.sendToDevice(tokensToNotify, payload);
  }
  
  functions.logger.log("No tokens to send to.");
  return null;

} catch(error) {
  functions.logger.error("Error sending chat notification:", error);
  return null;
}

});
3. The Service Worker (public/firebase-messaging-sw.js)
I am using the Firebase v8 SDK in the service worker for stability, as recommended in some tutorials. The firebaseConfig object contains the correct keys.
code
JavaScript
// public/firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.10.1/firebase-messaging.js');

const firebaseConfig = { /* My correct and complete firebase config */ };

firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();

messaging.onBackgroundMessage((payload) => {
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: payload.notification.icon,
data: { url: payload.data.url }
};
return self.registration.showNotification(notificationTitle, notificationOptions);
});

self.addEventListener('notificationclick', (event) => {
event.notification.close();
const urlToOpen = event.notification.data.url;
if (clients.openWindow && urlToOpen) {
return clients.openWindow(urlToOpen);
}
});
4. The Issue: Logs Analysis
The function logs show that everything works perfectly until the sendToDevice call:
Function execution started
Attempting to send notification to X token(s). (This log appears correctly)
Error sending chat notification: Error: An unknown server error was returned. Raw server response: "<TITLE>Not Found</TITLE>...". Status code: 404.
5. What I've Already Checked/Tried (The Debugging Journey)
Permissions: I have enabled both Firebase Cloud Messaging API and Cloud Pub/Sub API in my Google Cloud project.
IAM Roles: I have given the App Engine default service account the "Firebase Admin" role.
Tokens: The FCM tokens are correctly generated on the client and saved to a notificationTokens subcollection on my users documents. The function reads them correctly.
Library Versions: I've tried multiple versions of firebase-admin (v10, v11, v13) and firebase-functions (v4) without success. The current stable setup for my other functions is firebase-admin@^11.11.1 and firebase-functions@^4.9.0.
Gen 2 Migration: I tried migrating the functions to Gen 2, but ran into Functions codebase could not be analyzed successfully errors, which seems to be a separate environment issue. I would prefer to solve this with Gen 1 if possible.
It feels like I'm missing a fundamental configuration step in my Google Cloud project that prevents my function from authenticating correctly with the FCM service, despite the API being enabled.
Has anyone encountered this specific "404 Not Found" HTML response from the FCM backend when using sendToDevice from a 1st Gen function? Any ideas on what I might be missing?
Thank you in advance

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions