Jimmy Kane
Jimmy Kane

Reputation: 16825

Cannot save “custom blob” to Firestore - ADMIN SDK

Following up to an older question I had done here now I have the same problem with the admin SDK but cannot solve this.

I am trying to save a blob to the firestore but I get:

Error: Value for argument "data" is not a valid Firestore document. Couldn't serialize object of type "Blob" (found in field data). Firestore doesn't support JavaScript objects with custom prototypes (i.e. objects that were created via the "new" operator).

Here is how I convert my custom blob to a firestore blob:

// The import
import {firestore} from "firebase";

// The function 
export const parseQueue = functions.region('europe-west2').pubsub.schedule('every 1 minutes').onRun(async (context) => {

....code...

// The problem
writePromises.push(
          admin.firestore()
            .collection('users')
            .doc(userID)
            .collection('events')
            .doc(<string>event.getID())
            .collection('activities')
            .doc(<string>activity.getID())
            .collection('streams')
            .doc(stream.type)
            .set({
              type: stream.type,
              data: firestore.Blob.fromBase64String(new Buffer((Pako.gzip(JSON.stringify(stream.data), {to: 'string'})), 'binary').toString('base64')),
            }))

The above crashes when I call set with the error mentioned before.

The function firestore.Blob.fromBase64String works well and I do get back a blob that is fine.

What am I doing wrong?

Upvotes: 2

Views: 1252

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317477

The "firebase" module is not part of the Admin SDK, it's the client SDK. You can't mix usage of that with firebase-admin. Stick to only symbols and APIs provided by firebase-admin if you're going to pass them as parameters to firebase-admin SDK methods. You should probably remove the module "firebase" from your project completely.

You didn't show it, but I am assuming you already imported firebase-admin like one of these:

import * as admin from 'firebase-admin'
const admin = require('firebase-admin')

Now, any time you want to use Firestore APIs, you normally go through its provided firestore object:

const firestore = admin.firestore

You are already doing this once with your call to admin.firestore().collection().... It is basically re-exporting everything from the Cloud Firestore SDK for nodejs.

The Blob object you're using with the client SDK isn't provided by the server SDK. If you want to write a byte array, you will have to use node's Buffer object directly.

doc.set({
    type: stream.type,
    data: new Buffer((Pako.gzip(JSON.stringify(stream.data), {to: 'string'})), 'binary')
})

Or whatever you need to do to make the correct Buffer.

Upvotes: 4

Related Questions