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()
PY
Bug 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 None
The 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) # NameError
opentelemetry_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_skip evaluates check_dependencies() (already a @staticmethod on the prometheus instrument) before instantiating the dataclass, OR
- The optional-symbol references (
_make_collector_registry, tracer.start_as_current_span(...)) are guarded behind import_checker.is_*_installed at 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
Summary
FastStreamBootstrapperin lite-bootstrap 0.28.0 raisesNameErrorat bootstrap time whenever the corresponding optional extra (prometheusoropentelemetry) is not installed. The optional-import guard at module scope hides the missing symbol fromcheck_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
Bug 1 —
FastStreamPrometheusInstrument.__init__crashes beforecheck_dependencies()lite_bootstrap/bootstrappers/faststream_bootstrapper.py:BaseBootstrapper._register_or_skipinlite_bootstrap/bootstrappers/base.py:The dataclass
__init__evaluatesdefault_factoryunconditionally →prometheus_client.CollectorRegistry()→NameError: name 'prometheus_client' is not defined.check_dependencies()(which already exists on the class) never gets to short-circuit.Trace:
Bug 2 —
FastStreamHealthChecksInstrument.bootstrapreferences unboundtracerlite_bootstrap/bootstrappers/faststream_bootstrapper.py:opentelemetry_generate_health_check_spansdefaults toTrue(instruments/opentelemetry_instrument.py:48), so the branch is taken even when the opentelemetry extra is absent.Trace:
Expected behavior
Either:
_register_or_skipevaluatescheck_dependencies()(already a@staticmethodon the prometheus instrument) before instantiating the dataclass, OR_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
InstrumentDependencyMissingWarningmachinery already promises).Workaround
For Bug 1: subclass
FastStreamBootstrapperwithinstruments_typesrestricted to installed-extra instruments.For Bug 2: pass
opentelemetry_generate_health_check_spans=FalseonFastStreamConfig.Happy to send a PR if a fix shape is agreed.
Environment
faststream-logging,faststream-sentry,pyroscope