firebase / firebase-tools

The Firebase Command Line Tools
MIT License
4.04k stars 952 forks source link

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

Closed Girildo closed 1 year ago

Girildo commented 2 years ago

[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();

5. 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

<!-- Run the command with --debug flag, and include the logs below. -->
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:

? 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

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 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
anantakrishna commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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: https://github.com/firebase/firebase-tools/issues/4614#issuecomment-1155450187 . 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 commented 2 years ago

@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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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

inlined commented 2 years ago

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 commented 2 years ago

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.

giladmaker commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 1 year ago

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.

DibyodyutiMondal commented 1 year ago

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 commented 1 year ago

Will revisit - thanks @DibyodyutiMondal for the heads up.

DibyodyutiMondal commented 1 year ago

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

image

DibyodyutiMondal commented 1 year ago

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 commented 1 year ago

@DibyodyutiMondal Thanks for the followup.

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