Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Firebase functions emulator] Introducing a runtime error in the top level scope crashes the emulator. #4613

Closed
Girildo opened this issue Jun 3, 2022 · 18 comments

Comments

@Girildo
Copy link

Girildo commented Jun 3, 2022

[REQUIRED] Environment info

firebase-tools: 11.0.1

Platform: Windows

[REQUIRED] Test case

Any javascript runtime error in the global scope (that is, outside the body of any cloud function definition) crashes the emulator.

[REQUIRED] Steps to reproduce

  1. Run firebase init in an empty directory.
  2. Select only functions emulator, javascript (also happens with typescript), no eslint (also happens with eslint on), no default project (also happens when a project is selected).
  3. Run firebase emulators:start --only functions
  4. Open the automatically generated functions/index.js file and type something that results in a syntax error. E.g.:
const functions = require("firebase-functions");

// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
//   functions.logger.info("Hello logs!", {structuredData: true});
//   response.send("Hello from Firebase!");
// });
thisIsNotDefined();
  1. Observe how the emulator crashes with Error: Failed to load function definition from source: Failed to generate manifest from function source: ReferenceError: thisIsNotDefined is not defined

[REQUIRED] Expected behavior

The emulator does not crash.
It should issue a warning that it could not load the function code, but it should not crash, thereby also leaving other dangling processes running on the machine.

[REQUIRED] Actual behavior

Here the log of the firebase init command.

firebase init

     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##      
     ######    ##  ########  ######   ########  #########  ######  ######  
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##      
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

You're about to initialize a Firebase project in this directory:

  C:\dev\reprojs

Before we get started, keep in mind:

  * You are currently outside your home directory

? Are you ready to proceed? Yes
? Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. Functions: Configure a Cloud Functions directory and its files

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.

? Please select an option: Don't set up a default project

=== Functions Setup

A functions directory will be created in your project with sample code
pre-configured. Functions can be deployed with firebase deploy.

? What language would you like to use to write Cloud Functions? JavaScript  
? Do you want to use ESLint to catch probable bugs and enforce style? No
+  Wrote functions/package.json
+  Wrote functions/index.js
+  Wrote functions/.gitignore
? Do you want to install dependencies with npm now? Yes

added 238 packages, and audited 239 packages in 13s

15 packages are looking for funding
  run `npm fund` for details

3 high severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

i  Writing configuration info to firebase.json...
i  Writing project information to .firebaserc...
i  Writing gitignore file to .gitignore...

+  Firebase initialization complete!

And here the command that starts the emulator.

$ firebase emulators:start --only functions --debug
[2022-06-03T13:34:09.368Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
[2022-06-03T13:34:09.370Z] > authorizing via signed-in user (info@aestico.ch)
i  emulators: Starting emulators: functions {"metadata":{"emulator":{"name":"hub"},"message":"Starting emulators: functions"}}
[2022-06-03T13:34:09.386Z] [hub] writing locator at C:\Users\ggg94\AppData\Local\Temp\hub-testenvironmentaestico.json
!  functions: The following emulators are not running, calls to these services from the Functions emulator will affect production: auth, firestore, database, hosting, pubsub, storage {"metadata":{"emulator":{"name":"functions"},"message":"The following emulators are not running, calls to these services from the Functions emulator will affect production: \u001b[1mauth, firestore, database, hosting, pubsub, storage\u001b[22m"}}       
+  functions: Using node@16 from host. {"metadata":{"emulator":{"name":"functions"},"message":"Using node@16 from host."}}
[2022-06-03T13:34:09.418Z] defaultcredentials: writing to file C:\Users\ggg94\AppData\Roaming\firebase\info_aestico_ch_application_default_credentials.json
[2022-06-03T13:34:09.420Z] Setting GAC to C:\Users\ggg94\AppData\Roaming\firebase\info_aestico_ch_application_default_credentials.json {"metadata":{"emulator":{"name":"functions"},"message":"Setting GAC to C:\\Users\\ggg94\\AppData\\Roaming\\firebase\\info_aestico_ch_application_default_credentials.json"}}
[2022-06-03T13:34:09.424Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/testenvironmentaestico/adminSdkConfig [none]
[2022-06-03T13:34:09.716Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/testenvironmentaestico/adminSdkConfig 200
[2022-06-03T13:34:09.717Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/testenvironmentaestico/adminSdkConfig {"projectId":"testenvironmentaestico","databaseURL":"https://testenvironmentaestico-default-rtdb.europe-west1.firebasedatabase.app","storageBucket":"testenvironmentaestico.appspot.com","locationId":"europe-west6"}
[2022-06-03T13:34:09.740Z] Ignoring unsupported arg: auto_download {"metadata":{"emulator":{"name":"ui"},"message":"Ignoring unsupported arg: auto_download"}}
[2022-06-03T13:34:09.741Z] Ignoring unsupported arg: port {"metadata":{"emulator":{"name":"ui"},"message":"Ignoring unsupported arg: port"}}
[2022-06-03T13:34:09.741Z] Starting Emulator UI with command {"binary":"node","args":["--dns-result-order=ipv4first","C:\\Users\\ggg94\\.cache\\firebase\\emulators\\ui-v1.7.0\\server.bundle.js"],"optionalArgs":[],"joinArgs":false} {"metadata":{"emulator":{"name":"ui"},"message":"Starting Emulator UI with command {\"binary\":\"node\",\"args\":[\"--dns-result-order=ipv4first\",\"C:\\\\Users\\\\ggg94\\\\.cache\\\\firebase\\\\emulators\\\\ui-v1.7.0\\\\server.bundle.js\"],\"optionalArgs\":[],\"joinArgs\":false}"}}
i  ui: Emulator UI logging to ui-debug.log {"metadata":{"emulator":{"name":"ui"},"message":"Emulator UI logging to \u001b[1mui-debug.log\u001b[22m"}}
[2022-06-03T13:34:09.875Z] Web / API server started at localhost:4000
 {"metadata":{"emulator":{"name":"ui"},"message":"Web / API server started at localhost:4000\n"}}
i  functions: Watching "C:\dev\reprojs\functions" for Cloud Functions... {"metadata":{"emulator":{"name":"functions"},"message":"Watching \"C:\\dev\\reprojs\\functions\" for Cloud Functions..."}}
[2022-06-03T13:34:10.020Z] Validating nodejs source
[2022-06-03T13:34:11.520Z] > [functions] package.json contents: {
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "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": "16"
  },
  "main": "index.js",
  "dependencies": {
    "firebase-admin": "^10.0.2",
    "firebase-functions": "^3.18.0"
  },
  "devDependencies": {
    "firebase-functions-test": "^0.2.0"
  },
  "private": true
}
[2022-06-03T13:34:11.524Z] Building nodejs source
[2022-06-03T13:34:11.525Z] Analyzing nodejs backend spec
[2022-06-03T13:34:11.529Z] Could not find functions.yaml. Must use http discovery
[2022-06-03T13:34:11.740Z] Serving at port 9005

[2022-06-03T13:34:11.813Z] Got response from /__/functions.yaml {"endpoints":{},"specVersion":"v1alpha1","requiredAPIs":[]}
[2022-06-03T13:34:11.819Z] shutdown requested via /__/quitquitquit


┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://localhost:4000                │
└─────────────────────────────────────────────────────────────┘

┌───────────┬────────────────┬─────────────────────────────────┐
│ Emulator  │ Host:Port      │ View in Emulator UI             │
├───────────┼────────────────┼─────────────────────────────────┤
│ Functions │ localhost:5001 │ http://localhost:4000/functions │
└───────────┴────────────────┴─────────────────────────────────┘
  Emulator Hub running at localhost:4400
  Other reserved ports: 4500

Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.

[2022-06-03T13:34:19.899Z] File C:\dev\reprojs\functions\index.js changed, reloading triggers {"metadata":{"emulator":{"name":"functions"},"message":"File C:\\dev\\reprojs\\functions\\index.js changed, reloading triggers"}}
[2022-06-03T13:34:20.906Z] Validating nodejs source
[2022-06-03T13:34:22.387Z] > [functions] package.json contents: {
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "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": "16"
  },
  "main": "index.js",
  "dependencies": {
    "firebase-admin": "^10.0.2",
    "firebase-functions": "^3.18.0"
  },
  "devDependencies": {
    "firebase-functions-test": "^0.2.0"
  },
  "private": true
}
[2022-06-03T13:34:22.391Z] Building nodejs source
[2022-06-03T13:34:22.392Z] Analyzing nodejs backend spec
[2022-06-03T13:34:22.393Z] Could not find functions.yaml. Must use http discovery
[2022-06-03T13:34:22.608Z] Serving at port 9005

[2022-06-03T13:34:22.677Z] Got response from /__/functions.yaml Failed to generate manifest from function source: ReferenceError: thisIsNotDefined is not defined
[2022-06-03T13:34:22.680Z] Failed to parse functions.yamlincomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line at line 1, column 65:
     ...  function source: ReferenceError: thisIsNotDefined is not defined
                                         ^ {"name":"YAMLException","reason":"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line","mark":{"name":null,"buffer":"Failed to generate manifest from function source: ReferenceError: thisIsNotDefined is not defined\n\u0000","position":64,"line":0,"column":64},"message":"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line at line 1, column 65:\n     ...  function source: ReferenceError: thisIsNotDefined is not defined\n                                         ^"}
[2022-06-03T13:34:22.686Z] shutdown requested via /__/quitquitquit


Error: Failed to load function definition from source: Failed to generate manifest from function source: ReferenceError: thisIsNotDefined is not defined
@Girildo Girildo added the bug label Jun 3, 2022
@anantakrishna
Copy link

And not only emulator. Deployment also crashes:

i  deploying functions
Running command: npm --prefix "$RESOURCE_DIR" run lint
Running command: npm --prefix "$RESOURCE_DIR" run build
+  functions: Finished running predeploy script.
i  functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i  functions: ensuring required API cloudbuild.googleapis.com is enabled...
+  functions: required API cloudfunctions.googleapis.com is enabled
+  functions: required API cloudbuild.googleapis.com is enabled
i  functions: preparing codebase default for deployment

Error: Failed to load function definition from source: Failed to generate manifest from function source: Error: Empty token!

All I do is initializing the grammy bot:

const bot = new Bot(process.env.BOT_TOKEN ?? '');

On deployment the .secrets.local file is not loaded, neither the real secrets storage is accessed, I believe. In the emulator, seems that all the secret values are loaded only when the emulator is actually up and running (on the first request), but not during the startup time. Therefore, the code fails.

I guess this issue is related to #4538. According to how the fixing PR (#4541) is named, the process of evaluating the source code is called "Node discovery".

Interestingly, console.log is not printing anything in the console during this Node discovery.

firebase-tools: 11.0.1

Platform: Windows

@anantakrishna
Copy link

Just checked, the same issue occurs with emulator on firebase-tools@^10 and firebase-tools@^9.

Therefore, it seems to be a long-living issue/feature. However I don't tend to treat it as a feature because the documentation specifically suggests to use global variables to reuse objects in future invocations, but the described above issue effectively prevents us from doing so in many cases.

Recently I've asked a related question on SO, without answer yet: https://stackoverflow.com/q/72465657/3082178.

@yuchenshi
Copy link
Member

If I understand correctly, the OP is requesting that top-level runtime errors in general, such as thisIsNotDefined() that has nothing to do with process.env, not crash the emulator. This is a bug fix / feature request in the emulator only.

@anantakrishna I believe you have a different problem with OP, which is caused by environment variables not being available during discovery and startup. Please see the previous discussion for that: #4614 (comment) . If you have any more questions or context to add, please kindly comment on the thread linked above instead to help all of us stay on track with the issues.

@anantakrishna
Copy link

@yuchenshi yes, after adding my comments here and re-reading all, I realized that my problem is quite different. Excuse me for the mess, I'll switch to that discussion thread.

@feryardiant
Copy link

Hi

I came across similar errors but different case, in my case I'm using typescript, with :

firebase-tools: 11.1.0
Platform: MacOS Monterey 12.4

Here's the debug output:

$> pnpm emulator --only functions --debug

> @creasi/internal@0.0.0 emulator /Users/fery/Workspace/Creasico/Admin
> firebase emulators:start --export-on-exit --import .firebase/exports "--only" "functions" "--debug"

[2022-06-22T06:29:24.408Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
[2022-06-22T06:29:24.409Z] > authorizing via signed-in user (ferywardiyanto@creasi.co)
i  emulators: Starting emulators: functions {"metadata":{"emulator":{"name":"hub"},"message":"Starting emulators: functions"}}
[2022-06-22T06:29:24.422Z] [hub] writing locator at /var/folders/zp/n4dgglfn727gkv0ypyyjbp2w0000gn/T/hub-creasi-co.json
⚠  functions: The following emulators are not running, calls to these services from the Functions emulator will affect production: auth, firestore, database, hosting, pubsub, storage {"metadata":{"emulator":{"name":"functions"},"message":"The following emulators are not running, calls to these services from the Functions emulator will affect production: \u001b[1mauth, firestore, database, hosting, pubsub, storage\u001b[22m"}}
✔  functions: Using node@16 from host. {"metadata":{"emulator":{"name":"functions"},"message":"Using node@16 from host."}}
[2022-06-22T06:29:24.436Z] defaultcredentials: writing to file /Users/fery/.config/firebase/ferywardiyanto_creasi_co_application_default_credentials.json
[2022-06-22T06:29:24.436Z] Setting GAC to /Users/fery/.config/firebase/ferywardiyanto_creasi_co_application_default_credentials.json {"metadata":{"emulator":{"name":"functions"},"message":"Setting GAC to /Users/fery/.config/firebase/ferywardiyanto_creasi_co_application_default_credentials.json"}}
[2022-06-22T06:29:24.438Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/creasi-co/adminSdkConfig [none]
[2022-06-22T06:29:24.890Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/creasi-co/adminSdkConfig 200
[2022-06-22T06:29:24.890Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/creasi-co/adminSdkConfig {"projectId":"creasi-co","storageBucket":"creasi-co.appspot.com","locationId":"us-central"}
[2022-06-22T06:29:24.924Z] Ignoring unsupported arg: auto_download {"metadata":{"emulator":{"name":"ui"},"message":"Ignoring unsupported arg: auto_download"}}
[2022-06-22T06:29:24.924Z] Ignoring unsupported arg: port {"metadata":{"emulator":{"name":"ui"},"message":"Ignoring unsupported arg: port"}}
[2022-06-22T06:29:24.925Z] Starting Emulator UI with command {"binary":"node","args":["--dns-result-order=ipv4first","/Users/fery/.cache/firebase/emulators/ui-v1.7.0/server.bundle.js"],"optionalArgs":[],"joinArgs":false} {"metadata":{"emulator":{"name":"ui"},"message":"Starting Emulator UI with command {\"binary\":\"node\",\"args\":[\"--dns-result-order=ipv4first\",\"/Users/fery/.cache/firebase/emulators/ui-v1.7.0/server.bundle.js\"],\"optionalArgs\":[],\"joinArgs\":false}"}}
i  ui: Emulator UI logging to ui-debug.log {"metadata":{"emulator":{"name":"ui"},"message":"Emulator UI logging to \u001b[1mui-debug.log\u001b[22m"}}
[2022-06-22T06:29:25.110Z] Web / API server started at localhost:4000
 {"metadata":{"emulator":{"name":"ui"},"message":"Web / API server started at localhost:4000\n"}}
i  functions: Watching "/Users/fery/Workspace/Creasico/Admin/apps/functions" for Cloud Functions... {"metadata":{"emulator":{"name":"functions"},"message":"Watching \"/Users/fery/Workspace/Creasico/Admin/apps/functions\" for Cloud Functions..."}}
[2022-06-22T06:29:25.194Z] Validating nodejs source
[2022-06-22T06:29:28.256Z] > [functions] package.json contents: {
  "name": "func",
  "version": "0.0.0",
  "private": true,
  "license": "MIT",
  "main": "dist/index.js",
  "module": "dist/index.mjs",
  "types": "dist/types.d.ts",
  "engines": {
    "node": "16"
  },
  "scripts": {
    "build": "tsup",
    "deploy": "firebase deploy --only functions",
    "dev": "tsup --watch",
    "lint": "eslint --ext .ts,.json .",
    "logs": "firebase functions:log",
    "test": "mocha",
    "start": "firebase functions:shell"
  },
  "dependencies": {
    "@google-cloud/functions-framework": "^3.1.2",
    "cookie-parser": "^1.4.6",
    "express": "^4.18.1",
    "firebase-admin": "^10.3.0",
    "firebase-functions": "^3.21.2",
    "glob": "^8.0.3",
    "tslib": "^2.4.0"
  },
  "devDependencies": {
    "@antfu/eslint-config-ts": "^0.25.1",
    "@firebase/app-compat": "^0.1.27",
    "@firebase/app-types": "^0.7.0",
    "@firebase/util": "^1.6.1",
    "@types/cookie-parser": "^1.4.3",
    "@types/express": "^4.17.13",
    "@types/glob": "^7.2.0",
    "@types/node": "~16.11.41",
    "chai": "^4.3.6",
    "eslint": "^8.18.0",
    "firebase-functions-test": "^2.2.0",
    "jest": "^28.1.1",
    "mocha": "^9.2.2",
    "ts-node": "^10.8.1",
    "tsup": "^6.1.2",
    "typescript": "^4.7.4"
  },
  "eslintConfig": {
    "extends": [
      "@antfu/ts"
    ]
  }
}
[2022-06-22T06:29:28.257Z] Building nodejs source
[2022-06-22T06:29:28.257Z] Analyzing nodejs backend spec
[2022-06-22T06:29:28.258Z] Could not find functions.yaml. Must use http discovery
[2022-06-22T06:29:28.439Z] Serving at port 9005

[2022-06-22T06:29:28.474Z] Got response from /__/functions.yaml Failed to generate manifest from function source: TypeError [ERR_INVALID_URL]: Invalid URL
[2022-06-22T06:29:28.476Z] Failed to parse functions.yaml incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line at line 1, column 78:
     ... rce: TypeError [ERR_INVALID_URL]: Invalid URL
                                         ^ {"name":"YAMLException","reason":"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line","mark":{"name":null,"buffer":"Failed to generate manifest from function source: TypeError [ERR_INVALID_URL]: Invalid URL\n\u0000","position":77,"line":0,"column":77},"message":"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line at line 1, column 78:\n     ... rce: TypeError [ERR_INVALID_URL]: Invalid URL\n                                         ^"}
[2022-06-22T06:29:28.477Z] shutdown requested via /__/quitquitquit

i  emulators: Shutting down emulators. {"metadata":{"emulator":{"name":"hub"},"message":"Shutting down emulators."}}
i  ui: Stopping Emulator UI {"metadata":{"emulator":{"name":"ui"},"message":"Stopping Emulator UI"}}
⚠  Emulator UI has exited upon receiving signal: SIGINT 
i  functions: Stopping Functions Emulator {"metadata":{"emulator":{"name":"functions"},"message":"Stopping Functions Emulator"}}
i  hub: Stopping emulator hub {"metadata":{"emulator":{"name":"hub"},"message":"Stopping emulator hub"}}
i  logging: Stopping Logging Emulator {"metadata":{"emulator":{"name":"logging"},"message":"Stopping Logging Emulator"}}

Error: Failed to load function definition from source: Failed to generate manifest from function source: TypeError [ERR_INVALID_URL]: Invalid URL

Having trouble? Try firebase [command] --help
 ELIFECYCLE  Command failed with exit code 1.

@giladmaker
Copy link

Hi

I came across similar errors but different case, in my case I'm using typescript, with :

firebase-tools: 11.1.0 Platform: MacOS Monterey 12.4

Here's the debug output:
[2022-06-22T06:29:28.474Z] Got response from //functions.yaml Failed to generate manifest from function source: TypeError [ERR_INVALID_URL]: Invalid URL
[2022-06-22T06:29:28.476Z] Failed to parse functions.yaml incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line at line 1, column 78:
... rce: TypeError [ERR_INVALID_URL]: Invalid URL
^ {"name":"YAMLException","reason":"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line","mark":{"name":null,"buffer":"Failed to generate manifest from function source: TypeError [ERR_INVALID_URL]: Invalid URL\n\u0000","position":77,"line":0,"column":77},"message":"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line at line 1, column 78:\n ... rce: TypeError [ERR_INVALID_URL]: Invalid URL\n ^"}
[2022-06-22T06:29:28.477Z] shutdown requested via /
/quitquitquit

I'm facing this issue too.

$ firebase --version
11.1.0
$ node -v
v16.13.2
$ java --version
java 18.0.1.1 2022-04-22
Java(TM) SE Runtime Environment (build 18.0.1.1+2-6)
Java HotSpot(TM) 64-Bit Server VM (build 18.0.1.1+2-6, mixed mode, sharing)

@jakubcin
Copy link

i have the same problem :/ tried to change many things, downgrading, but nothing helps so far

@inlined
Copy link
Member

inlined commented Jul 1, 2022

We've see a number of concerns here.

  1. There's a request that we can handle errors thrown from global scope. This would be interesting, but it cannot be done. We're calling require on your code and it throws an Exception. That means require doesn't return a module and we have no handle to your functions for us to route traffic to you.
  2. Discussions about proccess.env.FOO not being available at discovery. We've got an extra feature coming soon that will let you have dependencies on variables during discovery (e.g. const foo = params.defineString("FOO"))
  3. Some of you are getting strange errors from our new discovery process. This is concerning. I personally write all of my code in TypeScript, so I'm not sure if that's the issue. Do you have tsc in your functions.beforeDeploy field in firebase.json? I don't know what the issue is yet; can you help me debug a bit more?

I'd love to know what CLI and SDK version you're using. I'd like to see what your function definitions look like (not the business logic, just the onRequest(options, callback) bits. And I'd like to see what our discovery process is generating. In your functions directory run FUNCTIONS_CONTROL_API=true PORT=8080 ./node_modules/.bin/firebase-functions .. Then from another terminal run curl -X GET http://localhost:8080/__/functions.yaml.

@giladmaker
Copy link

3. Some of you are getting strange errors from our new discovery process. This is concerning. I personally write all of my code in TypeScript, so I'm not sure if that's the issue. Do you have tsc in your functions.beforeDeploy field in firebase.json? I don't know what the issue is yet; can you help me debug a bit more?

I'd love to know what CLI and SDK version you're using. I'd like to see what your function definitions look like (not the business logic, just the onRequest(options, callback) bits. And I'd like to see what our discovery process is generating. In your functions directory run FUNCTIONS_CONTROL_API=true PORT=8080 ./node_modules/.bin/firebase-functions .. Then from another terminal run curl -X GET http://localhost:8080/__/functions.yaml.

Thanks for your reply.

  • Yes, my functions.predeploy field includes a tsc command. To be clear, it's all working well in terms of building and deploying the functions (firebase deploy), but I get the error (see my previous comment) when running the emulator (firebase emulate).
  • My CLI version is 11.1.0 and my firebase-functions sdk version is 3.21.2
  • I will try add more information re: function definitions and discovery endpoint output. BTW, I found the relevant area in my local Firebase CLI binaries (the detectFromPort function in the discovery module) and was able to log stuff to my console during the emulator startup (though nothing informative so far), so if you have ideas for stuff I should try log there, I can give that a try too.

@giladmaker
Copy link

And I'd like to see what our discovery process is generating. In your functions directory run...

Window 1:

$ FUNCTIONS_CONTROL_API=true PORT=8080 ./node_modules/.bin/firebase-functions .
Serving at port 8080
{"severity":"WARNING","message":"Warning, FIREBASE_CONFIG and GCLOUD_PROJECT environment variables are missing. Initializing firebase-admin will fail"}

Window 2:

$ curl -X GET http://localhost:8080/__/functions.yaml
Failed to generate manifest from function source: TypeError: Cannot read properties of undefined (reading 'length')

@tolgraven
Copy link

tolgraven commented Jul 4, 2022

We've see a number of concerns here.

  1. There's a request that we can handle errors thrown from global scope. This would be interesting, but it cannot be done. We're calling require on your code and it throws an Exception. That means require doesn't return a module and we have no handle to your functions for us to route traffic to you.

I think you're misunderstanding here. It's not that top level errors should somehow magically be made not broken. It's about not taking down the entire system (really uncleanly as well, as others have mentioned - can't even start it back up without manually killing java processes hogging the ports).

All it would require is... well surely nothing but a catch? If it throws, completely ignore it as far as state goes. Spew an error and otherwise pretend it never happened.

Every other hot reload software of all kinds have figured out how to do it, maybe due to my limited understanding but I don't get from your explanation why this would differ.

Why is the handle gone for good? And if entire env does indeed go toast and is impossible to retain when this happens why not simply reinitialize? Anything that doesn't cause a crash and involves a bunch of time killing processes so you can start the software again...

I was trying to quickly write a cloud function in Clojurescript and probably managed to crash everything 40 times while working out the kinks since being used to Figwheel and similar :w the document very often out of habit, before I at least managed to get a repl up and running and would only crash occasionally. Extreme example I'm sure, but incredibly frustrating!

@janakaud
Copy link

To add to @tolgraven's comment: things get worse when running emulators for Auth, Firestore etc as well, with local persistence; because now you don't have a way to clean-shutdown the orphaned Auth/Firestore process, and if you kill it (which you'd have to do anyways, at some point), you'll lose all Firestore data/changes from that session. (Even worse, in some cases, the local persistence store actually ends up corrupted - losing all your local application data, unless you have a previously-saved backup of the persistence directory.)

FWIW I'm currently running with node_modules/firebase-tools/lib/deploy/functions/runtimes/node/triggerParser.js patched (basically by commenting out all the process.send(..) calls), to prevent the Functions emulator from signaling back the code-loading error to the main/parent/controller process. This does prevent the "crash", but doesn't give any indication that code-loading actually failed either; logging the error/warning directly from the emulator code, didn't work (possibly because it runs as a child process; I couldn't dig deeper into the emulator architecture yet). Anyways, the emulator will keep on trying to re-load the code after every change detection, and eventually deploy the latest version once the load/parse error gets resolved.

As @tolgraven also mentioned, we love the emulator suite (esp. me, who hates needing to have a working/persistent internet connection during dev work); the emulator is our "cloud", and we're just saying that it would be perfect if outage of one service won't bring the whole "cloud" down.

taeold added a commit that referenced this issue Aug 4, 2022
…4826)

Functions Emulator features "hot-reloading" of users source to enable rapid iteration.

Today, when users edits their function code that produces runtime error (bound to happen during development), the entire Emulator Suite crashes! This problem gets worse if you are running other emulators like Auth and Firestore since the subprocesses are not cleaned up during the crash.

We modify the behavior of the Functions Emulator to simply emit an error log when we can't load function triggers from source code. This means that when an invalid source code for functions is used to start the Emulator, the Emulator will start and report an error instead of crashing immediately. Arguably, the latter is desirable since it makes their mistake more obvious, but I think the overall improvement in DevX is worth the change.

Example:

```
$ firebase emulators:start
i  emulators: Starting emulators: functions
⚠  functions: The following emulators are not running, calls to these services from the Functions emulator will affect production: auth, firestore, database, hosting, pubsub, storage
⚠  Your requested "node" version "14" doesn't match your global version "16". Using node@16 from host.
⚠  ui: Emulator UI unable to start on port 4000, starting on 4001 instead.
i  ui: Emulator UI logging to ui-debug.log
i  functions: Watching "/Users/danielylee/google/cf3-vpc/functions" for Cloud Functions...
⬢  functions: Failed to load function definition from source: FirebaseError: Failed to load function definition from source: Failed to generate manifest from function source: ReferenceError: aa is not defined

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://localhost:4001                │
└─────────────────────────────────────────────────────────────┘

┌───────────┬────────────────┬─────────────────────────────────┐
│ Emulator  │ Host:Port      │ View in Emulator UI             │
├───────────┼────────────────┼─────────────────────────────────┤
│ Functions │ localhost:5001 │ http://localhost:4001/functions │
└───────────┴────────────────┴─────────────────────────────────┘
  Emulator Hub running at localhost:4400
  Other reserved ports: 4500

Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.

✔  functions: Loaded functions definitions from source: vpc.
✔  functions[us-central1-vpc]: http function initialized (http://localhost:5001/danielylee-test-6/us-central1/vpc).
i  functions: Beginning execution of "vpc"
>  {"structuredData":true,"severity":"INFO","message":"Hello logs!"}
i  functions: Finished "vpc" in ~1s

## Make a change to the source code that produces runtime error:
⬢  functions: Failed to load function definition from source: FirebaseError: Failed to load function definition from source: Failed to generate manifest from function source: ReferenceError: aa is not defined

## You can still invoke existing function w/o problems
i  functions: Beginning execution of "vpc"
>  {"structuredData":true,"severity":"INFO","message":"Hello logs!"}
i  functions: Finished "vpc" in ~1s
```

Partially address #4613
@taeold
Copy link
Contributor

taeold commented Dec 29, 2022

Hi folks. I believe the issue raised in the original thread where failure to load the function crashes the parent emulator process is now fixed. I see some tangential concerns, and I hope those issues will be resolved in a new issue - please feel encouraged to create a new issue in this repo.

@taeold taeold closed this as completed Dec 29, 2022
@taeold taeold self-assigned this Dec 29, 2022
@DibyodyutiMondal
Copy link

While experiencing some other bugs, I noticed that this issue came back.

If the functions emulator can't discover the build, it crashes the process, but leaves the firestore emulator and the emulator ui running and blocking the ports.

@taeold
Copy link
Contributor

taeold commented Jan 31, 2023

Will revisit - thanks @DibyodyutiMondal for the heads up.

@DibyodyutiMondal
Copy link

Issue seems to be fixed in 11.22.0
While the original problem stll exists, emulator does not crash

image

@DibyodyutiMondal
Copy link

On a separate note, once I close the emulator (with ctrl+c, ctrl+c), the emulators shut down, but the firebase-debug.log contains many many many error logs which say the following:

[debug] [2023-02-01T03:32:11.094Z] Error: write EPIPE

In fact, it keeps logging it, till the end of the file, roughly 400 times, and I assume it stops because the process exits.
At any rate, I remember there was a time when the emulator would print out things like starting graceful shutdown of emulators. Press ctrl+c again to shut down immediately. But it has not done that for quite a while. And neither did I look too much into it, because the emulators seemed to have exited just fine.

I wonder if it's a related issue to this.

@taeold
Copy link
Contributor

taeold commented Feb 1, 2023

@DibyodyutiMondal Thanks for the followup.

Do you mind filing a separate issue for the latter case?

@taeold taeold closed this as completed Feb 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests