Skip to content

google-cloud-firestore: undeclared typing-extensions dependency causes ModuleNotFoundError #17244

@shokkunrf

Description

@shokkunrf

Determine this is the right repository

  • I determined this is the correct repository in which to report this bug.

Summary of the issue

Context

An application uses google-cloud-firestore (e.g. version 2.27.0) as a dependency on Python 3.10–3.13 and executes:

from google.cloud import firestore

Expected Behavior:

from google.cloud import firestore succeeds.

Actual Behavior:

from google.cloud import firestore fails with:

ModuleNotFoundError: No module named 'typing_extensions'

The root cause is in firestore itself: google/cloud/firestore_v1/async_transaction.py (line 31) directly imports typing_extensions, but the package does not declare it in setup.py or testing/constraints-*.txt. In practice this only fires when no other dependency provides typing-extensions transitively — most commonly when grpcio < 1.75.0 is resolved, which is within firestore's own declared range. To be explicit: grpcio < 1.75.0 is the trigger that exposes the defect, not the cause; the defect is firestore's undeclared direct import. See "Why this manifests" in Additional context for the full mechanism.

API client name and version

google-cloud-firestore 2.27.0

Reproduction steps: code

file: repro.sh

python -m venv venv
venv/bin/pip install "google-cloud-firestore" "grpcio==1.74.0"
venv/bin/python -c "from google.cloud import firestore"

Reproduction steps: supporting files

N/A

Reproduction steps: actual results

file: stderr.txt

Traceback (most recent call last):
  File "<string>", line 1, in <module>
    from google.cloud import firestore
  File ".../site-packages/google/cloud/firestore/__init__.py", line 18, in <module>
    from google.cloud.firestore_v1 import gapic_version as package_version
  File ".../site-packages/google/cloud/firestore_v1/__init__.py", line 33, in <module>
    from google.cloud.firestore_v1.async_client import AsyncClient
  File ".../site-packages/google/cloud/firestore_v1/async_client.py", line 50, in <module>
    from google.cloud.firestore_v1.async_transaction import AsyncTransaction
  File ".../site-packages/google/cloud/firestore_v1/async_transaction.py", line 31, in <module>
    from typing_extensions import Concatenate, ParamSpec, TypeVar
ModuleNotFoundError: No module named 'typing_extensions'

Reproduction steps: expected results

file: stderr.txt

(no output — import succeeds)

OS & version + platform

Debian GNU/Linux 13 (trixie)

Python environment

Python 3.13.13

Python dependencies

$ pip list
Package                  Version
------------------------ ---------
certifi                  2026.5.20
cffi                     2.0.0
charset-normalizer       3.4.7
cryptography             48.0.0
google-api-core          2.30.3
google-auth              2.53.0
google-cloud-core        2.6.0
google-cloud-firestore   2.27.0
googleapis-common-protos 1.75.0
grpcio                   1.74.0
grpcio-status            1.69.0
idna                     3.16
proto-plus               1.28.0
protobuf                 5.29.6
pyasn1                   0.6.3
pyasn1-modules           0.4.2
pycparser                3.0
requests                 2.34.2
urllib3                  2.7.0

Additional context

Why this manifests the way it does

  • typing-extensions was added to grpcio's requires_dist only in grpcio 1.75.0. Any grpcio in firestore's declared range (1.44.0–1.74.x on Python 3.10–3.13) does not pull typing-extensions in transitively, leaving firestore's own import unresolved.
  • The failure surfaces directly in firestore's own source code at async_transaction.py:31, not inside grpc. grpcio 1.74.0 does not use typing_extensions internally, so the import chain reaches firestore's undeclared import without any intermediate grpcio failure. This forecloses any "this is a grpcio bug" interpretation.
  • The bug is also statically visible in the source: async_transaction.py line 31 imports it, setup.py does not declare it.
  • Python 3.14 is incidentally protected (not actually fixed) by firestore's extra grpcio >= 1.75.1; python_version >= '3.14' constraint, which forces a grpcio version that does declare typing-extensions.

Even setting aside the runtime failure described above, firestore should declare what it directly imports, regardless of any particular grpcio version's transitive behavior. The fix is warranted on PEP 508 conformance grounds alone; the runtime failure on grpcio < 1.75 is just the most visible consequence of that violation. A sibling package in this monorepo (bigframes) already declares typing-extensions>=4.5.0,<5, so there is recent precedent for the declaration.

Workaround for affected users

Until a fix is released, applications hitting this bug can either:

  • Pin or constrain grpcio>=1.75.0 in their own requirements (gets typing-extensions transitively via grpcio's declaration), or
  • Add typing-extensions explicitly to their own requirements as a direct dependency.

The first workaround relies on grpcio 1.75.0 incidentally papering over the bug, not on a fix. Users who pin grpcio for legitimate reasons (downstream compatibility, OS package availability) cannot apply it and must use the second.

Recommended fix

Declare typing-extensions >= 4.5.0, < 5.0.0 in setup.py (matching the sibling bigframes package, which targets a release published after Python 3.11 GA). This keeps async_transaction.py:31 unchanged.

An alternative would be to switch that import to the stdlib typing module (Concatenate and ParamSpec are available there since Python 3.10), which would avoid adding a dependency at the cost of changing the import. Open to maintainer preference.

Happy to submit a PR for either direction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage meI really want to be triaged.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions