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.
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.
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.
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With