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

"Error: Can't determine Firebase Database URL." after v1 Migration from Beta #220

Closed
zgosalvez opened this issue Apr 6, 2018 · 33 comments
Closed

Comments

@zgosalvez
Copy link

Version info

firebase-functions: 1.0.0

firebase-tools: firebase/firebase-tools.git#ll-fixfbconfig2 (3.18.1) See firebase/firebase-tools/issues/722

firebase-admin: 5.11.0

Test case

See steps to reproduce. Related to /issues/216.

Steps to reproduce

  1. Create a sandbox Firebase project
  2. firebase init functions (Choose TypeScript and TSLint during setup)
  3. cd functions
  4. Add "express": "^4.16.3", in package.json
  5. rm -rf node_modules then npm install
  6. Replace index.ts with
import * as admin from 'firebase-admin';

admin.initializeApp();

exports['debug'] = require(`${__dirname}/debug.js`);
  1. Create debug.ts with
import * as express from 'express';
import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';

const app = express();

app.get('/', async (request, response) => {
    try {
        await admin.database().ref().once('value') as admin.database.DataSnapshot;
    } catch (error) {
        console.error(error);

        return response.status(500).send(error);
    }

    return response.status(200).send('OK');
});

export = functions.https.onRequest((request, response) => {
    // https://github.com/firebase/firebase-functions/issues/27#issuecomment-292768599

    if (!request.path) {
        request.url = `/${request.url}`;
    }

    return app(request, response);
});
  1. npm run deploy
  2. Access created function URL in a web browser, e.g. https://us-central1-project-id.cloudfunctions.net/debug

Were you able to successfully deploy your functions?

Yes.

Expected behavior

HTTP Response

Status Code: 200
Body: OK

Actual behavior

HTTP Response

Status Code: 500
Body: {"code":"database/invalid-argument","message":"Can't determine Firebase Database URL."}

Firebase Functions Logs

{ Error: Can't determine Firebase Database URL.
    at FirebaseDatabaseError.Error (native)
    at FirebaseDatabaseError.FirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:39:28)
    at new FirebaseDatabaseError (/user_code/node_modules/firebase-admin/lib/utils/error.js:190:23)
    at DatabaseService.ensureUrl (/user_code/node_modules/firebase-admin/lib/database/database.js:75:15)
    at DatabaseService.getDatabase (/user_code/node_modules/firebase-admin/lib/database/database.js:52:26)
    at FirebaseApp.database (/user_code/node_modules/firebase-admin/lib/firebase-app.js:235:24)
    at FirebaseNamespace.fn (/user_code/node_modules/firebase-admin/lib/firebase-namespace.js:283:45)
    at Object.<anonymous> (/user_code/lib/debug.js:16:21)
    at next (native)
    at /user_code/lib/debug.js:7:71
  errorInfo: 
   { code: 'database/invalid-argument',
     message: 'Can\'t determine Firebase Database URL.' } }
@ahaverty
Copy link

ahaverty commented Apr 6, 2018

@laurenzlong Unfortunately I'm seeing this again with some of my functions, but not all.
I've tried "firebase-tools": "https://github.com/firebase/firebase-tools.git#ll-fixfbconfig2" and still getting the same as @zgosalvez in a functions.database function.
I'm going to go back to the try catch initializeApp() in each function workaround I mentioned in #216

@zgosalvez
Copy link
Author

@ahaverty, with the above snippets. How would you implement the workaround?

@ahaverty
Copy link

ahaverty commented Apr 6, 2018

Remove the admin.initializeApp(); from index.ts
And add this under your imports in debug.ts

try {
    admin.initializeApp();
} catch(error) {
    //TODO: ignoring until firebase-functions fix released
}

@ahaverty
Copy link

ahaverty commented Apr 6, 2018

I've yet to hit issues with that, I'll update here if I do.
_If that doesn't fix it for you, it sounds like it's actually some weird timing/race issue and only working for me because of the time it takes to export all my functions. 🤔
Plan C if that doesn't work for you, is to add a tempFirebase to my firebase function configuration, which seems to be guaranteed to be gettable from index.ts (Let me know if it doesn't work for you, i'll join you in Plan C just to be safe 😄)

@zgosalvez
Copy link
Author

@ahaverty, that didn't work either; Same erroneous behavior.

@ahaverty
Copy link

ahaverty commented Apr 6, 2018

@zgosalvez Damn. Thoughts on using a temporary custom firebase config?

@zgosalvez
Copy link
Author

I want to hold off a more complicated workaround until we get feedback from @laurenzlong (or anyone from the Firebase team). This may be a simple fix on their end and I'm going to sleep soon. Thank goodness it's still the weekday in SFO. I'll hang ten for now. Feel free to do Plan C in the meantime. 🤓

@ahaverty
Copy link

ahaverty commented Apr 6, 2018

Deploying tonight (It's Friday in Ireland), I think I'll go with Plan C for now 🤓
I'll post up how it goes
Good night 👋 🌉

@ahaverty
Copy link

ahaverty commented Apr 6, 2018

According to @inlined (https://twitter.com/inlined/status/982277528751489025) we need to import firebase-functions before calling initializeApp()
Which I believe explains why some functions were working and others weren't.

@ahaverty
Copy link

ahaverty commented Apr 6, 2018

Ok, that didn't work either. console.log(process.env.FIREBASE_CONFIG) gives me undefined even after importing firebase-functions beforehand.
I also tried doing what firebase are doing, inside my functions:

import { AppOptions, initializeApp } from 'firebase-admin';

let firebaseConfig = JSON.stringify({
    databaseURL: `https://${process.env.GCLOUD_PROJECT}.firebaseio.com`,
    storageBucket: `${process.env.GCLOUD_PROJECT}.appspot.com`,
    projectId: process.env.GCLOUD_PROJECT,
});

initializeApp(firebaseConfig as AppOptions);

but I got this on deploy attempt:

Error: Error occurred while parsing your function triggers.

Error: Invalid Firebase app options passed as the first argument to initializeApp() for the app named "[DEFAULT]". Options must be a non-null object.
    at FirebaseAppError.Error (native)
    at FirebaseAppError.FirebaseError [as constructor] ...

@inlined
Copy link
Member

inlined commented Apr 6, 2018

TL;DR: Though it's a bit hacky, can you try requiring firebase-functions before calling admin.initializeApp()?

(background)
We are in the process of providing a server-side contract for Cloud Functions that lets you auto-initialize the Firebase Admin SDK, but that still hasn't completed unfortunately.

Until then, requiring firebase-functions will silently ensure the new model (the FIREBASE_CONFIG env var) on any environment deployed with the firebase CLI.

@ahaverty
Copy link

ahaverty commented Apr 6, 2018

@inlined I've tried import * as functions from 'firebase-functions' but it's still giving me the above + console.log(process.env.FIREBASE_CONFIG) is undefined.
Or do you mean call it as a require like: require('firebase-functions')?

@ahaverty
Copy link

ahaverty commented Apr 6, 2018

I just got the following working in my index.ts, although it looks like firebase-functions is favouring some internal firebase config call and if else'ing to this:

import { AppOptions, initializeApp } from 'firebase-admin';

initializeApp({
    databaseURL: `https://${process.env.GCLOUD_PROJECT}.firebaseio.com`,
    storageBucket: `${process.env.GCLOUD_PROJECT}.appspot.com`,
    projectId: process.env.GCLOUD_PROJECT,
});

Would you recommend sticking with this or going with the require('firebase-functions')? 🤔
Thanks for the help

@inlined
Copy link
Member

inlined commented Apr 6, 2018

Module loading in TypeScript has a few really subtle nuances to it; I think you've triggered lazy loading with the as statement. In TypeScript, you import a module for side effects with

import 'firebase-functions';

(a require statement would also work, though in some typescript configs you'll have to declare the existence of the require function first).

If the GCLOUD_PROJECT trick works for you, then that's fine as long as the code is not open source. There exist a small percentage of projects in the world where that code won't work. The databaseURL or storageBucket may not be the GCLOUD_PROJECT if the project is old enough.

@zgosalvez
Copy link
Author

@inlined, I changed the index.ts snippet to this and it worked (even on my actual project)! 👏🏼

// https://github.com/firebase/firebase-functions/issues/220#issuecomment-379312738
// tslint:disable-next-line:no-import-side-effect
import 'firebase-functions';

import * as admin from 'firebase-admin';

admin.initializeApp();

exports['debug'] = require(`${__dirname}/debug.js`);

It kind of makes sense now since I removed import * as functions from 'firebase-functions; when I migrated to v1. I noticed I wasn't using functions in index.ts so I removed it. I'll retain it until your server-side contract is complete. Importing in TypeScript is such a nuisance; I still can't get my head around it.
For now, I'll monitor the health of my functions in the coming days. Thanks for the new health dashboard in the Firebase console, and of course thank you for the insight into this issue. 🎉

@NeoLegends
Copy link

We are in the process of providing a server-side contract for Cloud Functions that lets you auto-initialize the Firebase Admin SDK, but that still hasn't completed unfortunately.

@inlined Why isn't this documented anywhere in the docs (at least doesn't seem like it)?

@inlined
Copy link
Member

inlined commented Apr 11, 2018

This was supposed to go away sooner. We're looking into ways to remove the subtlety rather than hiding it in docs. If we can't do this soon, then a doc note is certainly appropriate.

@bmachlin
Copy link

bmachlin commented Apr 18, 2018

I'm in the same situation except I'm using javascript. My first three lines are:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

And I'm also getting the "Can't determine Firebase Database URL" error when a firebase function is called. Specifically, when admin.database() is called.
version 3.18.4

@inlined
Copy link
Member

inlined commented Apr 18, 2018

Can you
A) Check your log lines to see whether there are warnings or errors being printed?
B) Give us the "dependencies" section of your package.json?

@bmachlin
Copy link

Good news: things suddenly started working again.

Bad news: I'm not sure why.

Basically I just did a whole bunch of npm installs and updates for everything I could.
A) The error I was getting (located inside the logs tab of the functions tab of the firebase console) was this:

Error: Can't determine Firebase Database URL.
at FirebaseDatabaseError.Error (native)
at FirebaseDatabaseError.FirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:39:28)
at new FirebaseDatabaseError (/user_code/node_modules/firebase-admin/lib/utils/error.js:190:23)
at DatabaseService.ensureUrl (/user_code/node_modules/firebase-admin/lib/database/database.js:74:15)
at DatabaseService.getDatabase (/user_code/node_modules/firebase-admin/lib/database/database.js:52:26)
at FirebaseApp.database (/user_code/node_modules/firebase-admin/lib/firebase-app.js:236:24)
at FirebaseNamespace.fn (/user_code/node_modules/firebase-admin/lib/firebase-namespace.js:296:42)
at exports.enqueue.functions.https.onRequest (/user_code/index.js:18:27)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/providers/https.js:26:41)
at /var/tmp/worker/worker.js:686:7

B) Here are the dependencies of the package.json file within the functions folder of my git repo:
"firebase-admin": "~5.8.1",
"firebase-functions": "^1.0.0"

@inlined
Copy link
Member

inlined commented Apr 19, 2018

Odd. Can you try the following lines after including firebase-functions?

const fs = require('fs');
console.log('FIREBASE_CONFIG is', process.env.FIREBASE_CONFIG);
console.log('GCLOUD_PROJECT is', process.env.GCLOUD_PROJECT);
console.log('runtime config is', require('./.runtimeconfig.json'));

(If you have other secrets in runtime config, you'll want to cut those out before sharing)

@bmachlin
Copy link

So runtimeconfig.json doesn't exist, but the output of the other two logs look normal:

GCLOUD_PROJECT is [project name]

FIREBASE_CONFIG is {"projectId":"[project name]","databaseURL":"https://[project name].firebaseio.com","storageBucket":"[project name].appspot.com"}

@inlined
Copy link
Member

inlined commented Apr 19, 2018

Oh. I read too fast and missed the part where everything started working again. I suspect that when you reran npm install, you upgraded either to the 1.0 version of firebase-functions, which sets the FIREBASE_CONFIG variable or to a newer version of firebase-admin, which can initialize from that variable. If things are now working, you shouldn't need to worry about regressing.

@Shery11
Copy link

Shery11 commented Apr 30, 2018

I had the same issue solved it like this

import * as admin from 'firebase-admin';
admin.initializeApp(functions.config().firebase);

@tmk1991
Copy link

tmk1991 commented May 9, 2018

@Shery11 That is only valid on versions < 1.0

@PierBover
Copy link

I also got the Can't determine Firebase Database URL error when using TypeScript.

I solved it by using @Shery11 's solution:

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp(functions.config().firebase);

This is a fresh project scaffolded today with the CLI. Here are my dependencies:

  "dependencies": {
    "firebase-admin": "^5.8.2",
    "firebase-functions": "^0.8.1"
  },
  "devDependencies": {
    "typescript": "^2.5.3"
  },

Why is the CLI configuring 0.8.1 instead of 1.1.0 ?

@laurenzlong
Copy link
Contributor

You must not have the latest CLI. firebase --version should print 3.19.3

@PierBover
Copy link

Thanks @laurenzlong that was it.

It's weird that the dependencies' versions are tied to the CLI version. I just scaffolded a TypeScript project and I got 1.0.3 instead of the latest 1.1.0.

The other thing that confused me is that I've been already using v1 of firebase-functions for months with previous CLI versions.

@laurenzlong
Copy link
Contributor

That's because the CLI hardcodes templates for "firebase init", for example https://github.com/firebase/firebase-tools/blob/master/templates/init/functions/typescript/package.lint.json. So what gets initialized depends on your CLI version.

@PierBover
Copy link

Thanks for the info.

Not such a great idea to hardcode templates if you ask me, but it's good to know.

@laurenzlong
Copy link
Contributor

Yeah I've been meaning to make it dynamically pull in the latest versions from npm... but it keeps falling behind on my to do list. Great chance to make a PR if anyone has some time on their hand!

joehan added a commit that referenced this issue Apr 18, 2019
* Scheduler

* unit tests

* Adds integration tests for scheduled functions

* removing uninented commit

* fixing version number

* adding labels and test for labels

* trigger tests off of call to cloud scheduler:run

* adding region/runtime opts tests

* Predictions Functions (#220)

* Firebase Predictions Integration with Functions - Initial check in

* Add predictions getter

* Make API match what was in the review, and add unit tests.

* Fix imports.

* Add error handling.

* Handle process.env.GCLOUD_PROJECT correctly.

* Fix region.

* Upper case RiskToleranceName.

* Add changelog message.

* formatting

* cleaning up

* Revert "Predictions Functions (#220)" (#226)

This reverts commit 838597aa6df973462a50484ec1f50d625da3f633.

* pr fixes

* adding clarifying comments

* starting on pubsub impl

* adds pusbub.schedule()

* switching tests over from https to pubsub

* Change timezone to a method instead of an optional argument

* use real eventType

* remove extra slash

* changelog

* switch signature to onRun(context)

* switches changelog to present tense
@Portur
Copy link

Portur commented Mar 17, 2020

Just want to add that adding firebase functions before initializeApp() worked for me.

The problem:

'use strict';

global['firebase_admin'] = require('firebase-admin');
firebase_admin.initializeApp();

The solution

'use strict';
global['firebase_functions'] = require('firebase-functions');
global['firebase_admin'] = require('firebase-admin');
firebase_admin.initializeApp();

@naveenrawat51
Copy link

admin.initializeApp(functions.config().firebase);
worked for me thanks @Shery11 you are a life saver :-) thanks again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests