Skip to content

Firestore pipelines union bug in firebase-js-sdk v12.11.0 #9764

@russellwheatley

Description

@russellwheatley

Operating System

macOS Sequoia

Environment (if applicable)

Chrome 146

Firebase SDK Version

12.11.0

Firebase SDK Product(s)

Firestore

Project Tooling

Rollup

Detailed Problem Description

A union query that works on v12.10.0 no longer works on v12.11.0. Specifically this:

const snapshot = await execute(
    db
      .pipeline()
      .collection(sf)
      .where(field('type').equal('Chinese'))
      .union(db.pipeline().collection(ny).where(field('type').equal('Italian'))) // I believe it is this
      .where(field('rating').greaterThanOrEqual(4.5))
      .sort(field('__name__').descending())
      .select('type', 'rating'),
  );

Error message:

FIRESTORE (12.11.0_lite) INTERNAL ASSERTION FAILED: Unexpected state (ID: ed)

Found this bug on React Native Firebase implementation when checking out latest version: https://github.com/invertase/react-native-firebase/blob/main/packages/firestore/e2e/Pipeline.e2e.js#L664-L673

I've since recreated on firebase-js-sdk to confirm it is upstream SDK bug.

Steps and code to reproduce issue

Run this on v12.10.0:

import { getApp, getApps, initializeApp, type FirebaseApp } from 'firebase/app';
import { getFirestore, collection, doc, setDoc } from 'firebase/firestore/lite';
import { execute, field } from 'firebase/firestore/lite/pipelines';

const config = {
// Your Config
};

const app: FirebaseApp = initializeApp(config);
const DATABASE_ID = "your-database-id";
const COLLECTION = "your-collection";

type UnionPipelineBugResult = {
  id: string | undefined;
  data: Record<string, unknown>;
};

export async function runUnionPipelineBug(): Promise<UnionPipelineBugResult[]> {
  const db = getFirestore(app, DATABASE_ID);
  const base = `${COLLECTION}/some-path/union`;
  const sf = collection(db, `${base}/SF/restaurants`);
  const ny = collection(db, `${base}/NY/restaurants`);

  await Promise.all([
    setDoc(doc(sf, 's1'), { type: 'Chinese', rating: 4.8 }),
    setDoc(doc(sf, 's2'), { type: 'Italian', rating: 4.9 }),
    setDoc(doc(ny, 'n1'), { type: 'Italian', rating: 4.7 }),
    setDoc(doc(ny, 'n2'), { type: 'Italian', rating: 3.7 }),
  ]);

  const snapshot = await execute(
    db
      .pipeline()
      .collection(sf)
      .where(field('type').equal('Chinese'))
      .union(db.pipeline().collection(ny).where(field('type').equal('Italian')))
      .where(field('rating').greaterThanOrEqual(4.5))
      .sort(field('__name__').descending())
      .select('type', 'rating'),
  );

  const results = snapshot.results.map(result => ({
    id: result.id,
    data: result.data() as Record<string, unknown>,
  }));

  console.log('[pipeline-bug] query results', { base, results });
  return results;
}

You will get a successful result:

[
  {
    "data": {
      "rating": 4.8,
      "type": "Chinese"
    }
  },
  {
    "data": {
      "type": "Italian",
      "rating": 4.7
    }
  }
]

But on the latest version, it produces the following error:

FIRESTORE (12.11.0_lite) INTERNAL ASSERTION FAILED: Unexpected state (ID: ed)

I also tested on the full Firestore SDK and got the same result:

FIRESTORE (12.11.0) INTERNAL ASSERTION FAILED: Unexpected state (ID: ed)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions