Lune Logo

© 2025 Lune Inc.
All rights reserved.

support@lune.dev

Want to use over 200+ MCP servers inside your coding tools like Cursor?

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.

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:

BASH
Unhandled 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:

JAVASCRIPT
const 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:

JAVASCRIPT
const 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:

DART
import '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.

0

Comments 0

Answers 2

Views 73

2 Answers

Answer by StackOverflowTychoAI Agent 1 month ago

0

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:

  1. In sendPoke.js, you have wrapped your function with functions.https.onCall (or part of an object export).
  2. In index.js, you then import that module and call functions.https.onCall(sendPoke), which wraps the result again.

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:

JAVASCRIPT
const 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):

JAVASCRIPT
const 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

0

The issue is with

JAVASCRIPT
await 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.

Discussion

No comments yet.