javascriptnode.jsfirebasegoogle-cloud-functionsfirebase-tools

ERR_NETWORK_IMPORT_DISALLOWED when I run `firebase emulators:start`


I am implementing a payment gateway. I am using Firebase Cloud Functions to run these APIs. I have a functions folder that has my functions and everything is set up for them. I am emulating the functions right now to check if everything is working.

When I run firebase emulators:start in the terminal, it shows ERR_NETWORK_IMPORT_DISALLOWED this error with error stack information. When I looked up the error it says that it could have something to do with using CommonJS and ESModule. I added in the package.json relating to the functions folder to use ESModule by adding this "type": "module" and still the error persists. The whole project is using ESModule. Also the functions were loaded before so I do not know what could cause this. I also tried using eslint and configuring it but it didn't show me anything. I also tried converting to CommonJS and still nothing. The index.js is as follows:

import functions from 'firebase-functions';
import pkg_ticket from './ticketFunctions.js';
import pkg_payment from './payment.js';

const { createTicket } = pkg_ticket;
const { createPaymentSession, verifyPayment } = pkg_payment; 

const createTicketFunction = functions.https.onRequest(createTicket);
const createPaymentSessionFunction = functions.https.onRequest(createPaymentSession);
const verifyPaymentFunction = functions.https.onRequest(verifyPayment);

export { createTicketFunction as createTicket, createPaymentSessionFunction as createPaymentSession, verifyPaymentFunction as verifyPayment };

And here is how I create a payment session:

const createPaymentSession = async (req, res) => {
    console.log('createPaymentSession function invoked');

    const { amount, currency, callbackUrl, orderId, customerEmail } = req.body;

    try {
        if (req.method === 'OPTIONS') {
            res.set('Access-Control-Allow-Origin', '*');
            res.set('Access-Control-Allow-Methods', 'GET, POST');
            res.set('Access-Control-Allow-Headers', 'Content-Type');
            res.status(204).send('');
            return;
        }
        res.set('Access-Control-Allow-Origin', '*');

        const paymentRequest = {
            amount,
            currency,
            callbackUrl,
            merchantPublicKey: MERCHANT_PUBLIC_KEY,
            orderId,
            customerEmail
        };

        const response = await axios.post(`${GEIDEA_API_URL}/checkout`, paymentRequest, {
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Basic ${Buffer.from(`${MERCHANT_PUBLIC_KEY}:${MERCHANT_API_PASSWORD}`).toString('base64')}`
            }
        });

        const paymentUrl = response.data.redirectUrl;

        if (!paymentUrl) {
            return res.status(400).json({ message: "Failed to create payment session" });
        }

        res.status(200).json({
            message: "Payment session created successfully",
            paymentUrl
        });

    } catch (error) {
        console.error('Error creating payment session:', error);
        res.status(500).json({ message: 'Internal server error.' });
    }
};

ps: It also gave me a warning that the requested node version was 18 while the version I am using is 22. I tried to change it in the package.json to be 22 but still the same warning. I don't know if that contributes to my problem or not.

I will post the debug info that appeared when I ran firebase emulators:start --debug, it is quite long lol.

package.json contents:

{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "type": "module",
  "scripts": {
    "serve": "firebase emulators:start --only functions",
    "shell": "firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "18"
  },
  "main": "index.js",
  "dependencies": {
    "firebase-admin": "^12.7.0",
    "firebase-functions": "^6.3.0",
    "functions": "file:"
  },
  "devDependencies": {
    "firebase-functions-test": "^3.1.0"
  },
  "private": true
}
[2025-03-05T20:49:28.298Z] Building nodejs source
[2025-03-05T20:49:28.299Z] Failed to find version of module node: reached end of search path D:\Develo\TicketRunners\TicketRunners\functions\node_modules
!  functions: Your requested "node" version "18" doesn't match your global version "22". Using node@22 from host.
[2025-03-05T20:49:28.302Z] Could not find functions.yaml. Must use http discovery
[2025-03-05T20:49:28.308Z] Found firebase-functions binary at 'D:\Develo\TicketRunners\TicketRunners\functions\node_modules\.bin\firebase-functions'
Serving at port 8866

TypeError: ERR_NETWORK_IMPORT_DISALLOWED is not a constructor
    at ModuleLoader.getModuleJobForRequire (node:internal/modules/esm/loader:376:15)
    at new ModuleJobSync (node:internal/modules/esm/module_job:341:34)
    at ModuleLoader.getModuleJobForRequire (node:internal/modules/esm/loader:444:11)
    at new ModuleJobSync (node:internal/modules/esm/module_job:341:34)
    at ModuleLoader.getModuleJobForRequire (node:internal/modules/esm/loader:444:11)
    at new ModuleJobSync (node:internal/modules/esm/module_job:341:34)
    at ModuleLoader.importSyncForRequire (node:internal/modules/esm/loader:357:11)
    at loadESMFromCJS (node:internal/modules/cjs/loader:1385:24)
    at Module._compile (node:internal/modules/cjs/loader:1536:5)
    at Object..js (node:internal/modules/cjs/loader:1706:10)

[2025-03-05T20:49:28.566Z] Got response code 400; body Failed to generate manifest from function source: TypeError: ERR_NETWORK_IMPORT_DISALLOWED is not a constructor   
!!  functions: Failed to load function definition from source: FirebaseError: Functions codebase could not be analyzed successfully. It may have a syntax or runtime error {"metadata":{"emulator":{"name":"functions"},"message":"Failed to load function definition from source: FirebaseError: Functions codebase could not be analyzed successfully. It may have a syntax or runtime error"}}
[2025-03-05T20:49:32.595Z] Could not find VSCode notification endpoint: FetchError: request to http://localhost:40001/vscode/notify failed, reason: . If you are not running the Firebase Data Connect VSCode extension, this is expected and not an issue.

Solution

  • So I have fixed the issue by doing two things.

    First thing is I switched the syntax from being written as ESModule to be written as CommonJS. That helped work around some dependencies not being able to work with ESModule.

    Second thing was that instead of getting the db instance from firebase.js script that is used by the rest of the project, I created and admin instance in one of my functions file and then I got the firestore db using const db = admin.firestore(); and then exported it with the rest of the functions in the file.

    Both of these solutions allowed the emulator to read the functions correctly and then export it to the emulator's environment.

    Here is the updated payment.js lines that made the difference:

    const functions = require('firebase-functions');
    const axios = require('axios');
    const admin = require("firebase-admin");
    
    if (!admin.apps.length) {
        admin.initializeApp();
    }
    const db = admin.firestore();
    
    //rest of the code
    
    module.exports = { createPaymentSession, verifyPayment, db};
    

    And then in index.js I adapted to that change and added an example function:

    const functions = require('firebase-functions');
    const { createTicket } = require('./ticketFunctions');
    const { createPaymentSession, verifyPayment, db } = require('./payment');
    
    exports.createTicket = functions.https.onRequest(createTicket);
    exports.createPaymentSession = functions.https.onRequest(createPaymentSession);
    exports.verifyPayment = functions.https.onRequest(verifyPayment);
    
    exports.exampleFunction = functions.https.onRequest(async (req, res) => {
        const snapshot = await db.collection("tickets").get();
        const tickets = snapshot.docs.map(doc => doc.data());
    
        res.status(200).json({ tickets });
    });
    
    

    That fixed the issue and now the emulator reads the functions properly.