Running `firebase deploy` results in Error: functions predeploy error: Command terminated with non-zero exit code2
Device: MacBook Pro
Operating system version: macOS Catalina (version 10.15.1)
Swift version:
Apple Swift version 5.1.2 (swiftlang-1100.0.278 clang-1100.0.33.9) Target: x86_64-apple-darwin19.0.0
Node Version:
node v12.14.0 (npm v6.13.4)
Firebase --version
7.10.0
What steps will reproduce the problem:
- Clone project
- Follow project steps as outlined in
- Step 3 in Part 9 Create a Cloud Function results in an error.
What is the expected result?
- running
firebase deployshould result in success with terminal output ofDeploy complete!
What happens instead of that?
running firebase deploy results in error with terminal output:
› firebase deploy
=== Deploying to 'myfriendlyeats-625e0'...
i deploying functions
Running command: npm --prefix $RESOURCE_DIR run lint
> functions@ lint /Users/uzo/Code/Learning/personal/firestore-codelab-extended-swift/functions
> tslint -p tslint.json
Running command: npm --prefix $RESOURCE_DIR run build
> functions@ build /Users/uzo/Code/Learning/personal/firestore-codelab-extended-swift/functions
> tsc
node_modules/firebase-functions/lib/function-configuration.d.ts:4:64 - error TS1005: ']' expected.
4 export declare const SUPPORTED_REGIONS: readonly ["us-central1", "us-east1", "us-east4", "europe-west1", "europe-west2", "asia-east2", "asia-northeast1"];
~
node_modules/firebase-functions/lib/function-configuration.d.ts:4:66 - error TS1134: Variable declaration expected.
4 export declare const SUPPORTED_REGIONS: readonly ["us-central1", "us-east1", "us-east4", "europe-west1", "europe-west2", "asia-east2", "asia-northeast1"];
~~~~~~~~~~
node_modules/firebase-functions/lib/function-configuration.d.ts:4:153 - error TS1005: ';' expected.
4 export declare const SUPPORTED_REGIONS: readonly ["us-central1", "us-east1", "us-east4", "europe-west1", "europe-west2", "asia-east2", "asia-northeast1"];
~
node_modules/firebase-functions/lib/function-configuration.d.ts:16:61 - error TS1005: ']' expected.
16 export declare const VALID_MEMORY_OPTIONS: readonly ["128MB", "256MB", "512MB", "1GB", "2GB"];
~
node_modules/firebase-functions/lib/function-configuration.d.ts:16:63 - error TS1134: Variable declaration expected.
16 export declare const VALID_MEMORY_OPTIONS: readonly ["128MB", "256MB", "512MB", "1GB", "2GB"];
~~~~~~~
node_modules/firebase-functions/lib/function-configuration.d.ts:16:93 - error TS1005: ';' expected.
16 export declare const VALID_MEMORY_OPTIONS: readonly ["128MB", "256MB", "512MB", "1GB", "2GB"];
~
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! functions@ build: `tsc`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the functions@ build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/uzo/.npm/_logs/2019-12-18T02_09_55_474Z-debug.log
Error: functions predeploy error: Command terminated with non-zero exit code2
Contents of debug.log
0 info it worked if it ends with ok
1 verbose cli [
1 verbose cli '/Users/uzo/.nvm/versions/node/v12.14.0/bin/node',
1 verbose cli '/Users/uzo/.nvm/versions/node/v12.14.0/bin/npm',
1 verbose cli '--prefix',
1 verbose cli '/Users/uzo/Code/Learning/personal/firestore-codelab-extended-swift/functions',
1 verbose cli 'run',
1 verbose cli 'build'
1 verbose cli ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'prebuild', 'build', 'postbuild' ]
5 info lifecycle functions@~prebuild: functions@
6 info lifecycle functions@~build: functions@
7 verbose lifecycle functions@~build: unsafe-perm in lifecycle true
8 verbose lifecycle functions@~build: PATH: /Users/uzo/.nvm/versions/node/v12.14.0/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/Users/uzo/Code/Learning/personal/firestore-codelab-extended-swift/functions/node_modules/.bin:/Users/uzo/.rvm/gems/ruby-2.6.3/bin:/Users/uzo/.rvm/gems/ruby-2.6.3@global/bin:/Users/uzo/.rvm/rubies/ruby-2.6.3/bin:/Users/uzo/.nvm/versions/node/v12.14.0/bin:/Users/uzo/.gem/bin:/Users/uzo/bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/uzo/.rvm/bin
9 verbose lifecycle functions@~build: CWD: /Users/uzo/Code/Learning/personal/firestore-codelab-extended-swift/functions
10 silly lifecycle functions@~build: Args: [ '-c', 'tsc' ]
11 silly lifecycle functions@~build: Returned: code: 2 signal: null
12 info lifecycle functions@~build: Failed to exec build script
13 verbose stack Error: functions@ build: `tsc`
13 verbose stack Exit status 2
13 verbose stack at EventEmitter.<anonymous> (/Users/uzo/.nvm/versions/node/v12.14.0/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:332:16)
13 verbose stack at EventEmitter.emit (events.js:210:5)
13 verbose stack at ChildProcess.<anonymous> (/Users/uzo/.nvm/versions/node/v12.14.0/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack at ChildProcess.emit (events.js:210:5)
13 verbose stack at maybeClose (internal/child_process.js:1021:16)
13 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:283:5)
14 verbose pkgid functions@
15 verbose cwd /Users/uzo/Code/Learning/personal/firestore-codelab-extended-swift
16 verbose Darwin 19.0.0
17 verbose argv "/Users/uzo/.nvm/versions/node/v12.14.0/bin/node" "/Users/uzo/.nvm/versions/node/v12.14.0/bin/npm" "--prefix" "/Users/uzo/Code/Learning/personal/firestore-codelab-extended-swift/functions" "run" "build"
18 verbose node v12.14.0
19 verbose npm v6.13.4
20 error code ELIFECYCLE
21 error errno 2
22 error functions@ build: `tsc`
22 error Exit status 2
23 error Failed at the functions@ build script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 2, true ]
Looks like this is the same error as https://github.com/firebase/firebase-functions/issues/404. It's a really long and messy thread, so you don't have to read the whole thing, but the cause of the error is you're running a different version of typescript than the one that Functions expects.
Can you share the versions in your package.json file?
@morganchen12 : I resolved my issue using 3 steps:
- I updated my package.json file to use firebase-admin version 8.0.0 and above. My package.json file currently looks like this:
{
"name": "functions",
"scripts": {
"lint": "./node_modules/.bin/tslint -p tslint.json",
"build": "./node_modules/.bin/tsc",
"serve": "npm run build && firebase serve --only functions",
"shell": "npm run build && firebase experimental:functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "^8.0.0",
"firebase-functions": "^3.3.0"
},
"devDependencies": {
"tslint": "^5.20.0",
"typescript": "^2.9.2"
},
"private": true,
"engines": {
"node": "8"
}
}
- Added the additional step of running
npm run buildas suggested in firebase/firestore-codelab-extended-swift/issues/27
After this change, running firebase deploy resulted in new error messages:
src/index.ts:27:20 - error TS2532: Object is possibly 'undefined'.
27 const rating = eventData.rating;
~~~~~~~~~
src/index.ts:32:28 - error TS2532: Object is possibly 'undefined'.
32 const prevRating = previousValue.rating;
~~~~~~~~~~~~~
src/index.ts:39:26 - error TS2532: Object is possibly 'undefined'.
39 const restaurantID = eventData.restaurantID;
~~~~~~~~~
src/index.ts:44:27 - error TS2532: Object is possibly 'undefined'.
44 const difference = previousValue.rating - rating
~~~~~~~~~~~~~
src/index.ts:61:21 - error TS2532: Object is possibly 'undefined'.
61 const oldRating = restaurantDoc.data().averageRating;
~~~~~~~~~~~~~~~~~~~~
src/index.ts:62:25 - error TS2532: Object is possibly 'undefined'.
62 const oldNumReviews = restaurantDoc.data().reviewCount;
~~~~~~~~~~~~~~~~~~~~
which suggested either a mistype on my end or a change in how typescript evaluates code.
This stackoverflow question helped me figure out what to do. Thus the new contents of my index.ts file are:
// Copyright (c) 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
type Firestore = admin.firestore.Firestore;
const app = admin.initializeApp();
export const computeAverageReview = functions.firestore
.document('reviews/{reviewId}').onWrite((change, context) => {
const eventData = change.after!.data();
const prev = change.before;
const rating = eventData!.rating;
let previousValue
if (prev.exists) {
previousValue = prev.data();
const prevRating = previousValue?.rating;
if (rating === prevRating) {
console.log("not a new rating.");
return null;
}
}
const restaurantID = eventData!.restaurantID;
const db = app.firestore()
if (prev.exists) {
const difference = previousValue?.rating - rating
return updateAverage(db, restaurantID, difference, true);
} else {
return updateAverage(db, restaurantID, rating, false);
}
});
async function updateAverage(db: Firestore, restaurantID: string, newRating: number, prev: boolean) {
const updateDB = db.collection('restaurants').doc(restaurantID);
const restaurantDoc = await updateDB.get();
if (!restaurantDoc.exists) {
console.log("Document does not exist!");
return null;
}
const oldRating = restaurantDoc?.data()?.averageRating;
const oldNumReviews = restaurantDoc?.data()?.reviewCount;
let newNumReviews = oldNumReviews+1;
let newAvgRating = ((oldRating*oldNumReviews)+newRating)/newNumReviews;
if (prev) {
newNumReviews = oldNumReviews;
newAvgRating = ((oldRating*oldNumReviews)-newRating)/oldNumReviews;
}
await updateDB.update({averageRating: newAvgRating, reviewCount: newNumReviews});
console.log("average updated");
return null;
}
/**
* TODO(DEVELOPER): Write the updateRest Function here.
*/
/**
*TODO(DEVELOPER): Add updateRestaurant helper function here.
*/
Let me know what you think. Thanks
PS: the force unwrapping of the values makes me nervous. Is this the recommended way to do this? I could leave things like this for now till I wrap up the workshop and then look further into Typescript BUT if you have any insights that would be greatly appreciated as it would speed up my learning. Thanks
Thanks for investigating, looks like the Typescript in the codelab needs to be updated.
The unwrapping is not the best way to do this, because it creates a tight coupling between your server function and the client. For example, in the review update handler, this line:
const eventData = change.after!.data();
will break if you ever add a feature to delete reviews to the app, since after will be undefined. In a complex, long-lived, and frequently-updated app, you will inevitably have users who choose to remain on older versions instead of upgrading their apps, so it's good to not tightly couple your functions to an app version's implementation because that inflexibility will cost you in the future.
Functions makes this easier since deploying is pretty easy and the functions themselves are stateless. So you could just add the force-unwraps as they are now and then just change them when you want to update your app. In the case of a few force-unwraps, this is only viable because removing the unwraps and handling the error case is easy.
I am getting this same error. I went through and updated my dependencies in my package.json, but that didn't work.
@C2SO can you file a new issue with your compiler/linter error?
No solution to this yet?
same problem !!
Same problem, appeared out of nowhere.. Haven't changed a bit in the code.
Same problem
Try running "firebase init hosting" before the deploy command