oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
72.46k stars 2.6k forks source link

Firestore Protobuf Issue `null is not an object` / `Couldn't serialize object` #12432

Open brianmhunt opened 4 weeks ago

brianmhunt commented 4 weeks ago

What version of Bun is running?

1.1.18

What platform is your computer?

Linux 5.15.0-1054-gcp x86_64 x86_64

What steps can reproduce the bug?

Basically following the instructions to setup Firestore [1] -- noting that some auth / a Firebase project will be needed.

$ bun i firebase-admin
import { initializeApp } from 'firebase-admin/app';
import { getFirestore, FieldValue } from 'firebase-admin/firestore';

async function main () {
  initializeApp();
  const db = getFirestore();
  const aTuringRef = db.collection('users').doc('aturing');

  await aTuringRef.set({
    'first': 'Alan',
    'middle': 'Mathison',
    'last': 'Turing',
    'born': 1912,
    timestamp: FieldValue.serverTimestamp(),
  });

}

main()

[1] https://firebase.google.com/docs/firestore/quickstart#node.js

What is the expected behavior?

Write or read the given document via the Firebase / Firestore API i.e. node compatibility.

What do you see instead?

On Write (the example above):

329 |     }
330 |     else if (value === null) {
331 |         // Ok.
332 |     }
333 |     else if (typeof value === 'object') {
334 |         throw new Error((0, validate_1.customObjectMessage)(arg, value, path));
                    ^
error: Value for argument "data" is not a valid Firestore document. Couldn't serialize object of type "ServerTimestampFieldValueImpl" (found in field "timestamp"). Firestore doesn't support JavaScript objects with custom prototypes (i.e. objects that were created via the "new" operator).
      at validateUserInput (/home/brian_minutebox_com/minutebox/services/datastore/node_modules/@google-cloud/firestore/build/src/serializer.js:334:15)
      at validateUserInput (/home/brian_minutebox_com/minutebox/services/datastore/node_modules/@google-cloud/firestore/build/src/serializer.js:271:13)
      at validateDocumentData (/home/brian_minutebox_com/minutebox/services/datastore/node_modules/@google-cloud/firestore/build/src/write-batch.js:597:22)
      at set (/home/brian_minutebox_com/minutebox/services/datastore/node_modules/@google-cloud/firestore/build/src/write-batch.js:258:9)
      at set (/home/brian_minutebox_com/minutebox/services/datastore/node_modules/@google-cloud/firestore/build/src/reference.js:396:37)
      at /home/brian_minutebox_com/minutebox/services/datastore/s.ts:12:20
      at main (/home/brian_minutebox_com/minutebox/services/datastore/s.ts:7:21)
      at /home/brian_minutebox_com/minutebox/services/datastore/s.ts:22:1

On Read:

110 |      * @private
111 |      * @internal
112 |      * @param {Object} timestamp The `Timestamp` Protobuf object.
113 |      */
114 |     static fromProto(timestamp) {
115 |         return new Timestamp(Number(timestamp.seconds || 0), timestamp.nanos || 0);
                                          ^
TypeError: null is not an object (evaluating 'timestamp.seconds')
      at fromProto (/home/brian_minutebox_com/minutebox/services/datastore/node_modules/@google-cloud/firestore/build/src/timestamp.js:115:37)
      at transform (/home/brian_minutebox_com/minutebox/services/datastore/node_modules/@google-cloud/firestore/build/src/reference.js:1976:56)
      at node:stream:3383:45
      at writeOrBuffer (node:stream:2722:27)
      at node:stream:2705:40
      at ondata (node:stream:2204:22)
      at emit (node:events:180:48)
      at addChunk (node:stream:2029:22)
      at readableAddChunk (node:stream:1983:30)
      at node:stream:3385:40

Additional information

For Auth see:

Firebase admin console:

brianmhunt commented 3 weeks ago

Related:

brianmhunt commented 1 week ago

This appears to be working in bun 1.21.

Also noting a change to the repro to use FieldValue.serverTimestamp (instead of importing from firebase/firestore.

brianmhunt commented 6 days ago

I spoke too soon. The fail is no longer consistent, but it still does occur sporadically on the same data with the same command. So it might be a race condition of sorts. In any case I'll reopen - though noting that I only reproduced it with code more complex than the reproduction. The reproduction above might still illustrate the problem but I wanted to note that I have not tested it with many repetitions. The stack remains the same:

CleanShot 2024-07-30 at 14 57 35@2x