sgl-project/sglang · error · AttributeError
{name}
Error message
{name} What it means
The breakable CUDA graph runner wraps a transformer and forwards unknown attribute lookups to it via __getattr__. It deliberately reads self.__dict__['transformer'] to avoid recursing through __getattr__; if 'transformer' is not yet assigned — before/during __init__ or after a failed one — the KeyError is re-raised as AttributeError(name) for the requested name.
Source
Thrown at python/sglang/multimodal_gen/runtime/breakable_cuda_graph/runner.py:253
self.entries: dict[tuple, _CaptureEntry] = {}
# Signatures we have given up capturing (capture raised); run eager.
self._blocked: set[tuple] = set()
self._disabled_reason: str | None = None
self.max_entries = max(0, _env_int("SGLANG_DIFFUSION_BCG_MAX_ENTRIES", 32))
# LTX-2 dual-tower blocks carry 6 attention break points each
# (video/audio self, video/audio prompt-cross, a2v, v2a), so 48 blocks
# capture ~289 segments; keep headroom above that.
self.max_segments = max(0, _env_int("SGLANG_DIFFUSION_BCG_MAX_SEGMENTS", 512))
def __getattr__(self, name: str) -> Any:
# Only reached for attributes the runner itself does not define; proxy
# them to the wrapped transformer so callers can treat the runner as a
# transparent stand-in. Use __dict__ to avoid recursing through
# __getattr__ before ``transformer`` is assigned in __init__.
try:
transformer = self.__dict__["transformer"]
except KeyError as e: # pragma: no cover - during/ before __init__
raise AttributeError(name) from e
return getattr(transformer, name)
# ------------------------------------------------------------------ #
# Public capture / replay API
# ------------------------------------------------------------------ #
@torch.no_grad()
def capture(self, **kwargs) -> bool:
"""Capture a graph for ``kwargs``'s signature if not already captured.
Idempotent: returns ``True`` when a graph is available for the
signature afterwards (already captured or newly captured), ``False``
when capture is disabled/blocked or failed (the caller then runs eager).
"""
if self._disabled_reason is not None:
return False
key = self._signature(kwargs)
if key in self._blocked:
return FalseView on GitHub (pinned to 0132848349)
Solutions
- Check the traceback for an earlier failure — if __init__ crashed, fix that so 'transformer' is always assigned.
- Move attribute access out of base-class __init__ or defer it until after super().__init__() completes.
- If the attribute lives on the model, access it via runner.transformer.<attr> explicitly once initialized.
Example fix
// before
class MyRunner(BreakableCudaGraphRunner):
def __init__(self):
self.debug_flag = self.enable_debug # hits __getattr__ pre-init
super().__init__(...)
// after
class MyRunner(BreakableCudaGraphRunner):
def __init__(self):
super().__init__(...)
self.debug_flag = self.enable_debug Defensive patterns
Strategy: validation
Validate before calling
runner = BreakableCudaGraphRunner(...)
attr = getattr(runner, "some_attr", None)
if attr is None and "transformer" in runner.__dict__:
attr = getattr(runner.transformer, "some_attr") Type guard
def runner_ready(runner) -> bool:
return "transformer" in runner.__dict__ Try / catch
try:
val = runner.some_attr
except AttributeError:
if "transformer" not in runner.__dict__:
logger.error("runner not initialized; original __init__ likely failed")
raise Prevention
- Never touch runner attributes from base-class __init__ before super().__init__().
- Wrap teardown/logging of failed constructions in hasattr checks.
- Access wrapped-model attributes via runner.transformer explicitly where possible.
When it happens
Trigger: Accessing any attribute that exists on neither the runner nor (once initialized) the wrapped transformer, or any attribute access before __init__ assigned self.transformer — e.g. from a base-class constructor, a __init__ exception path, or unpickling that bypasses __init__.
Common situations: A crash inside runner __init__ followed by cleanup/logging code touching runner attributes; subclass overrides running before super().__init__(); copy/pickle or debuggers touching a partially constructed object; typos in attribute names that were expected on the wrapped transformer.
Related errors
- Z-Image caption tensor must have rank 2 or 3
- 'Req' object has no attribute 'sampling_params'
- '{}' object has no attribute '{}'
- Could not access latents of provided encoder_output
- --bcg-text-buckets must contain at least one positive intege
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/904932425fe621be.
Report an issue: GitHub.