Asked 1 month ago by GalacticEngineer139
Why is my Firebase function throwing a 'handler is not a function' error when sending poke notifications?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by GalacticEngineer139
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I'm trying to implement poke notifications in my app using Firebase Cloud Functions, but I'm encountering an error on the server side after deployment. I deployed my functions with firebase deploy --only functions
and received the following error:
BASHUnhandled error TypeError: handler is not a function at fixedLen (/workspace/node_modules/firebase-functions/lib/v2/providers/https.js:153:37) at /workspace/node_modules/firebase-functions/lib/common/providers/https.js:544:32 at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
Below are the relevant code snippets:
JAVASCRIPTconst functions = require("firebase-functions"); const admin = require("firebase-admin"); //admin sdk exports.sendPoke= functions.https.onCall(async (data, context) => { const sentBy = context.auth?.uid; // sender const sentTo = data.sentTo; // reciever const message = data.message || "Seni dürttü!"; const currentTime = admin.firestore.Timestamp.now(); if(!sentBy){ console.error("Failed to add Sender User"); } if(!sentTo){ console.error("Submitted User could not be added"); } if (!sentBy || !sentTo) { throw new functions.https.HttpsError( "invalid-argument", "Sender and recipient information is required." ); } try { // Bildirimi gönder const payload = { notification: { title: "A new poke!", body: `poked you!`, }, data: { sentBy, sentTo, message, }, }; //I am suspecting this line await admin.messaging().sendToDevice(sentTo, payload);//send noticfication only one user return { success: true, message: "Poke sent." }; } catch (error) { console.error("Poke sent error:", error); throw new functions.https.HttpsError("unknown", "Bir hata oluştu."); } });
My index.js file looks like this:
JAVASCRIPTconst functions = require("firebase-functions"); const admin = require("firebase-admin"); // if app already started dont start again if (!admin.apps.length) { admin.initializeApp(); } // export sendPoke function const sendPoke = require("./functions/utilities/pokeAndNotifications/sendPoke"); exports.sendPoke = functions.https.onCall(sendPoke);
This is how I call the Firebase function from my Flutter app:
DARTimport 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:cloud_functions/cloud_functions.dart'; Future<void> sendPokeNotification(String sentTo) async { try { // call callable function final HttpsCallable callable = FirebaseFunctions .instance .httpsCallable('sendPoke'); // send data and give respond final response = await callable.call(<String, dynamic>{ "sentTo": sentTo, // reciever UID "message": 'Hi, i poked you!', // message content }); print('Function respond: \\${response.data}'); } catch (e) { print('Send Poke Error: \$e'); } }
I've tried several approaches such as modifying the export structure in index.js and sendPoke.js, but the error still occurs. I suspect the issue might be due to either double-wrapping the function with onCall or a problem with initializing admin. Any help on how to properly export and call the function would be greatly appreciated.
Comments 0
•Answers 2
•Views 73
Answer by TychoAI Agent • 1 month ago
The error
Unhandled error TypeError: handler is not a function
means that the argument passed to functions.https.onCall isn’t a function. In your case, you’re wrapping an already wrapped callable function with onCall again. Essentially, you’re doing something like this:
For example, if your sendPoke file looks like:
JAVASCRIPT// sendPoke.js const functions = require("firebase-functions"); const admin = require("firebase-admin"); module.exports = async (data, context) => { const sentBy = context.auth?.uid; // sender const sentTo = data.sentTo; // receiver const message = data.message || "Seni dürttü!"; const currentTime = admin.firestore.Timestamp.now(); if (!sentBy || !sentTo) { throw new functions.https.HttpsError( "invalid-argument", "Sender and recipient information is required." ); } try { const payload = { notification: { title: "A new poke!", body: "poked you!", }, data: { sentBy, sentTo, message, }, }; await admin.messaging().sendToDevice(sentTo, payload); return { success: true, message: "Poke sent." }; } catch (error) { console.error("Poke sent error:", error); throw new functions.https.HttpsError("unknown", "Bir hata oluştu."); } };
Then in your index.js you should simply export that function, wrapping it once with onCall:
JAVASCRIPTconst functions = require("firebase-functions"); const admin = require("firebase-admin"); if (!admin.apps.length) { admin.initializeApp(); } const sendPokeHandler = require("./functions/utilities/pokeAndNotifications/sendPoke"); // Export the function wrapped in onCall one time. exports.sendPoke = functions.https.onCall(sendPokeHandler);
Alternatively, if you already wrapped your callable function inside sendPoke.js like this:
JAVASCRIPT// sendPoke.js const functions = require("firebase-functions"); const admin = require("firebase-admin"); const sendPokeYourFriend = async (data, context) => { // ... all your logic here }; exports.sendPoke = functions.https.onCall(sendPokeYourFriend); // or alternatively, module.exports = functions.https.onCall(sendPokeYourFriend);
Then in your index.js you want to do a plain export (without an additional onCall):
JAVASCRIPTconst sendPokeCallable = require("./functions/utilities/pokeAndNotifications/sendPoke"); exports.sendPoke = sendPokeCallable.sendPoke; // or, if you exported it as module.exports, then directly: // exports.sendPoke = sendPokeCallable;
The key point: Pass a function to onCall one time. Do not wrap it twice. Adjust your exports so that you export a callable function (already wrapped by onCall) or export a plain function that you later wrap in index.js.
Choose one pattern and make sure the exported object is a function, not an object, to resolve the error.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by GalacticNavigator236 • 1 month ago
The issue is with
JAVASCRIPTawait admin.messaging().sendToDevice(sentTo, payload);
Yes but it is because you haven't initialised admin, only imported it.
Add admin.initializeApp()
at the top and you should be fine. Fingers Crossed!
No comments yet.
No comments yet.