Repository navigation
FastStream bootstrapper NameError when prometheus / opentelemetry extras are not installed #87
Description
Summary
FastStreamBootstrapper in lite-bootstrap 0.28.0 raises NameError at bootstrap time whenever the corresponding optional extra (prometheus or opentelemetry) is not installed. The optional-import guard at module scope hides the missing symbol from check_dependencies(), but two code paths reference the gated symbol unconditionally and trip before any dependency check has a chance to run.
I hit this on a service that intentionally installs only lite-bootstrap[faststream-logging,faststream-sentry,pyroscope] because it runs on NAT'd edge hosts where Prometheus scraping is impractical and there are no downstream hops to trace.
Reproduction
uv venv && uv pip install 'lite-bootstrap[faststream-logging,faststream-sentry]==0.28.0' faststream[rabbit] uvicorn
python - <<'PY'
from faststream.asgi import AsgiFastStream
from faststream.rabbit import RabbitBroker
from lite_bootstrap import FastStreamBootstrapper, FastStreamConfig
config = FastStreamConfig(
application=AsgiFastStream(RabbitBroker("amqp://guest:guest@localhost/")),
service_name="repro",
service_debug=False,
)
FastStreamBootstrapper(config).bootstrap()
PYBug 1 — FastStreamPrometheusInstrument.__init__ crashes before check_dependencies()
lite_bootstrap/bootstrappers/faststream_bootstrapper.py:
if import_checker.is_prometheus_client_installed:
import prometheus_client
def _make_collector_registry() -> "prometheus_client.CollectorRegistry":
return prometheus_client.CollectorRegistry() # NameError when extra missing
@dataclasses.dataclass(kw_only=True, frozen=True)
class FastStreamPrometheusInstrument(PrometheusInstrument):
collector_registry: "prometheus_client.CollectorRegistry" = dataclasses.field(
default_factory=_make_collector_registry, init=False
)BaseBootstrapper._register_or_skip in lite_bootstrap/bootstrappers/base.py:
def _register_or_skip(self, instrument_type):
instrument = instrument_type(bootstrap_config=...) # crashes here
if not instrument.check_dependencies(): # never reached
warnings.warn(...)
return NoneThe dataclass __init__ evaluates default_factory unconditionally → prometheus_client.CollectorRegistry() → NameError: name 'prometheus_client' is not defined. check_dependencies() (which already exists on the class) never gets to short-circuit.
Trace:
File ".../lite_bootstrap/bootstrappers/base.py", line 41, in __init__
if (instrument := self._register_or_skip(instrument_type)) is not None:
File ".../lite_bootstrap/bootstrappers/base.py", line 45, in _register_or_skip
instrument = instrument_type(bootstrap_config=self.bootstrap_config)
File "<string>", line 4, in __init__
File ".../lite_bootstrap/bootstrappers/faststream_bootstrapper.py", line 138, in _make_collector_registry
return prometheus_client.CollectorRegistry()
NameError: name 'prometheus_client' is not defined
Bug 2 — FastStreamHealthChecksInstrument.bootstrap references unbound tracer
lite_bootstrap/bootstrappers/faststream_bootstrapper.py:
if import_checker.is_opentelemetry_installed:
from opentelemetry import trace
tracer: typing.Final = trace.get_tracer(__name__)
@dataclasses.dataclass(...)
class FastStreamHealthChecksInstrument(HealthChecksInstrument):
def bootstrap(self) -> None:
...
if self.bootstrap_config.opentelemetry_generate_health_check_spans:
check_health = tracer.start_as_current_span(...)(check_health) # NameErroropentelemetry_generate_health_check_spans defaults to True (instruments/opentelemetry_instrument.py:48), so the branch is taken even when the opentelemetry extra is absent.
Trace:
File ".../lite_bootstrap/bootstrappers/faststream_bootstrapper.py", line 91, in bootstrap
check_health = tracer.start_as_current_span(f"GET {self.bootstrap_config.health_checks_path}")(
NameError: name 'tracer' is not defined
Expected behavior
Either:
_register_or_skipevaluatescheck_dependencies()(already a@staticmethodon the prometheus instrument) before instantiating the dataclass, OR- The optional-symbol references (
_make_collector_registry,tracer.start_as_current_span(...)) are guarded behindimport_checker.is_*_installedat call site.
Either fix would let users install lite-bootstrap with a subset of extras and have the unused instruments skip themselves quietly (which is what the InstrumentDependencyMissingWarning machinery already promises).
Workaround
For Bug 1: subclass FastStreamBootstrapper with instruments_types restricted to installed-extra instruments.
For Bug 2: pass opentelemetry_generate_health_check_spans=False on FastStreamConfig.
Happy to send a PR if a fix shape is agreed.
Environment
- lite-bootstrap 0.28.0
- faststream 0.x (rabbit extra)
- Python 3.14
- Installed extras:
faststream-logging,faststream-sentry,pyroscope
Activity
fix: prevent FastStream bootstrap NameError when optional extras are …
lesnik512 commentedon May 13, 2026
Thanks for the detailed report, @hasansezertasan — both traces made the bugs easy to pin down. Fixed in #88:
_register_or_skipnow checks dependencies before instantiating the instrument, so missing optional extras are skipped cleanly via the existing warning.tracercall is now guarded byimport_checker.is_opentelemetry_installed.Added regression tests for both. Released in 0.28.1.
hasansezertasan commentedon May 14, 2026
Thanks for the quick fix @lesnik512 🚀.