Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing file in firebase storage results in 403 ("The project to be billed is associated with an absent billing account")

I'm developing a Firebase Cloud Function that collects the metadata from a file stored in Firebase's Storage

My code is pretty much this:

const { Storage } = require('@google-cloud/storage');
const storage = new Storage();

exports.someFunction = functions.https.onCall((data, context) => {
    getMetadata("myBucket", data.filename)
        .then(() => {
            console.log("OK");
            return;
        })
        .catch(err => {
            console.error(err);
        })

    // do some other stuff here ....

    return;
}

async function getMetadata(bucketName, filename) {
    const [metadata] = await storage
        .bucket(bucketName)
        .file(filename)
        .getMetadata();  <<== ERROR HAPPENS IN THIS CALL

    console.log(metadata.selfLink);
    console.log(metadata.size);
}

Whenever storage.bucket(bucketName).file(filename).getMetadata() is called, as indicated in the code above, it results in a 403 with "The project to be billed is associated with an absent billing account." I've tried running it both locally (with firebase functions:shell) and deployed. Here's the full error message:

{ Error: The project to be billed is associated with an absent billing account.
    at Util.parseHttpRespBody (/srv/node_modules/@google-cloud/common/build/src/util.js:191:38)
    at Util.handleResp (/srv/node_modules/@google-cloud/common/build/src/util.js:135:117)
    at retryRequest (/srv/node_modules/@google-cloud/common/build/src/util.js:423:22)
    at onResponse (/srv/node_modules/retry-request/index.js:200:7)
    at /srv/node_modules/teeny-request/build/src/index.js:222:13
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:229:7)
  code: 403,
  errors: 
   [ { domain: 'global',
       reason: 'accountDisabled',
       message: 'The project to be billed is associated with an absent billing account.',
       locationType: 'header',
       location: 'Authorization' } ],
  response: undefined,
  message: 'The project to be billed is associated with an absent billing account.' }

That Firebase project has been on "Blaze plan" for a few weeks now and the billing account has been enabled for about a year, being charged for other GCP projects as well.

I've read the service account should have "signBlob" permission, which which I tried by adding "Service Account Token Creator" to both the default AppEngine Service Account and the Firebsae Service Account.

I've also tried initializing the storage via Firebase's admin SDK

const serviceAccount = require("path-to-json-downloaded-from-firebase-console.json");
admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://<my-project>.firebaseio.com"
});
const storage = admin.storage();

But no luck with either.

I couldn't figure out which account is 'disabled' or 'absent' nor what else I should configure to get this running and got stuck.

Any pointers that could get me troubleshoot further would help a lot.

like image 832
mauronr Avatar asked May 06 '19 03:05

mauronr


People also ask

How do I reference Firebase Storage?

To create a reference, get an instance of the Storage service using getStorage() then call ref() with the service as an argument. This reference points to the root of your Cloud Storage bucket.

Which one is used to store media files in Firebase?

Cloud Storage for Firebase stores your files in a Google Cloud Storage bucket, making them accessible through both Firebase and Google Cloud. This allows you the flexibility to upload and download files from mobile clients via the Firebase SDKs for Cloud Storage.


1 Answers

The cause was my misunderstanding of what "bucket" and "filename" are in the calls in the code.

In my case entering bucketName as gs://[my-project].appspot.com and fileName as the full path under the bucket fixed the issue.

More explicitly, the arguments should have been like:

const [metadata] = await storage
        .bucket("gs://[my-project].appspot.com")
        .file("path1/path2/actual-file-name")
        .getMetadata();
like image 177
mauronr Avatar answered Sep 22 '22 01:09

mauronr