Skip to content

fix(firestore): accept pipeline references from the same client before initialization - #9196

Open
Om-singhaI wants to merge 1 commit into
googleapis:mainfrom
Om-singhaI:fix/firestore-pipeline-reference-before-init
Open

fix(firestore): accept pipeline references from the same client before initialization#9196
Om-singhaI wants to merge 1 commit into
googleapis:mainfrom
Om-singhaI:fix/firestore-pipeline-reference-before-init

Conversation

@Om-singhaI

Copy link
Copy Markdown

fix(firestore): accept pipeline references from the same client before initialization

Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:

  • Make sure to open an issue as a bug/issue before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea
  • Ensure the tests and linter pass
  • Code coverage does not decrease (if any source code was changed)
  • Appropriate docs were updated (if necessary)

Fixes #9186 🦕

What was wrong

With a client that has no explicit projectId (the common case on Cloud Run, Cloud Functions, GCE and anywhere else the project is picked up from the environment), this throws before any request is made:

const firestore = new Firestore();
firestore.pipeline().documents([firestore.doc('users/user1')]);
// Error: INTERNAL ERROR: Client is not yet ready to issue requests.

PipelineSource.documents() and PipelineSource.collection() call _validateReference() for every DocumentReference or CollectionReference they are given. That method compares reference.firestore.formattedName against this.db.formattedName. Firestore.formattedName reads the projectId getter, and that getter throws until initializeIfNeeded() has detected the project, which only happens when the first request is issued. Pipeline construction is synchronous and happens before any request, so a fresh client always hit this path. The same pipeline built from the string path (documents(['users/user1'])) worked because this.db.doc(path) never touches the project ID. The stack trace in the issue (get projectId -> get formattedName -> _validateReference -> documents) is exactly this.

The fix

_validateReference now returns early when reference.firestore === this.db. A reference created by the pipeline's own Firestore instance necessarily targets the same database, so there is nothing to compare and no reason to read the project ID. References that come from a different Firestore instance still go through the existing formattedName comparison, so the cross database error message and behaviour are unchanged.

The change is nine lines in dev/src/pipelines/pipelines.ts and does not touch documents(), collection() or any stage, so it should not conflict with #9118.

A note on scope: if a reference comes from a different Firestore instance and either instance has not detected its project ID yet, the comparison still throws the same INTERNAL ERROR as before. Handling that would mean either comparing the private _projectId fields (which can both be undefined before detection, so there is nothing meaningful to compare) or deferring the check to execution time after initializeIfNeeded(). I kept this PR to the case from the issue, which is also the overwhelmingly common one, and would be glad to follow up on the multi instance case if you want it handled.

Tests

New describe('PipelineSource reference validation') block in dev/test/pipelines/pipeline.ts:

  • accepts a DocumentReference before the project ID is detected: builds the client with createInstance(..., {projectId: undefined}) and a getProjectId override, so the project ID is unknown until the first request. Builds pipeline().documents([firestore.doc('foo/bar')]), executes it, and asserts the ExecutePipeline request targets projects/detected-project/databases/(default) with a documents stage whose argument is /foo/bar.
  • accepts a CollectionReference before the project ID is detected: same setup with pipeline().collection(firestore.collection('foo')).
  • rejects a DocumentReference that targets a different database and rejects a CollectionReference that targets a different database: a reference from a second client with databaseId: 'other-db' still throws the existing "does not match the database name" error. These pin the behaviour the early return must not change.

Verification

All runs were in handwritten/firestore with npm run compile followed by mocha build/test/pipelines/pipeline.js (the same file npm test runs under c8). The unit tests use the existing createInstance fake client and need no GCP credentials.

  • Pristine main (48e0941): a script mirroring the gist from the issue printed INTERNAL ERROR: Client is not yet ready to issue requests. for both documents([firestore.doc(...)]) and collection(firestore.collection(...)), with the same get projectId -> get formattedName -> _validateReference stack as the report, while the string path forms succeeded.
  • New tests with the source change reverted to main (test file only changed): 6 passing, 2 failing. The two "accepts" tests fail with Error: INTERNAL ERROR: Client is not yet ready to issue requests.; the two "rejects" tests pass on main as expected.
  • New tests with the fix: 8 passing, 0 failing. The reproduction script now prints OK for all four forms.
  • Full package unit suite with the fix (npm run test-only, which is c8 mocha build/test): 696 passing, 47 pending, 0 failing. The 47 pending tests are pre existing skipped tests; none are in the files this PR touches.
  • Conformance suite with the fix (mocha build/conformance --exit): 228 passing, 0 failing. Without --exit the conformance process prints the same 228 passing summary and then stays alive on an open handle; it does exactly the same with the sources from main, so that is pre existing and unrelated to this change.

Coverage: the only new source lines are the early return and its condition, and both branches are exercised by the new tests (same instance returns early, different instance falls through to the existing comparison), so line and branch coverage of pipelines.ts go up.

Lint

npx prettier --config .prettierrc.js --check passes on both changed files. ESLint passes on both files with the package's gts config, plugin:prettier/recommended and the Firestore specific overrides copied from the root .eslintrc.json (explicit return types, no-console, no-restricted-properties for .only, no-floating-promises). I ran it this way because I installed only the Firestore package rather than the monorepo root; the root eslint-plugin-import and eslint-plugin-promise rule sets were therefore not run locally, but the change adds no imports and the new tests use async/await in the same style as the surrounding tests.

…e initialization

Passing a DocumentReference or CollectionReference to pipeline().documents()
or pipeline().collection() threw "INTERNAL ERROR: Client is not yet ready to
issue requests." whenever the Firestore instance had no explicit project ID
and had not yet issued a request. PipelineSource._validateReference compared
reference.firestore.formattedName with the pipeline's own formattedName, and
that getter reads the projectId getter, which throws until
initializeIfNeeded() has detected the project. Pipeline construction is
synchronous and happens before any request, so a fresh client always hit
this path. Passing the same location as a string path worked because that
code never reads the project ID.

A reference created by the same Firestore instance necessarily targets the
same database, so _validateReference now returns early when
reference.firestore is the pipeline's own instance and only compares
formatted names for references that come from a different instance. The
existing cross database check is unchanged.

Adds unit tests that build and execute a pipeline from a DocumentReference
and from a CollectionReference on a client whose project ID is only detected
on the first request, plus tests that references targeting a different
database are still rejected.

Fixes googleapis#9186
@Om-singhaI
Om-singhaI requested a review from a team as a code owner August 23, 2026 01:20
@product-auto-label product-auto-label Bot added the api: firestore Issues related to the Firestore API. label Aug 23, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modifies the PipelineSource reference validation to bypass database comparison when the reference's Firestore instance is identical to the pipeline's instance, preventing errors when the project ID is not yet detected. It also adds corresponding unit tests. The feedback suggests changing the return statement from 'return true;' to a simple 'return;' to maintain consistency with the validation method's implicit void return type.

Comment thread handwritten/firestore/dev/src/pipelines/pipelines.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: firestore Issues related to the Firestore API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Passing DocumentReference to Firestore.pipeline().documents() throws "Error: INTERNAL ERROR: Client is not yet ready to issue requests."

1 participant