{"record":{"id":"904932425fe621be","repo":"sgl-project/sglang","slug":"name","errorCode":null,"errorMessage":"{name}","messagePattern":"\\{name\\}","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/breakable_cuda_graph/runner.py","lineNumber":253,"sourceCode":"        self.entries: dict[tuple, _CaptureEntry] = {}\n        # Signatures we have given up capturing (capture raised); run eager.\n        self._blocked: set[tuple] = set()\n        self._disabled_reason: str | None = None\n        self.max_entries = max(0, _env_int(\"SGLANG_DIFFUSION_BCG_MAX_ENTRIES\", 32))\n        # LTX-2 dual-tower blocks carry 6 attention break points each\n        # (video/audio self, video/audio prompt-cross, a2v, v2a), so 48 blocks\n        # capture ~289 segments; keep headroom above that.\n        self.max_segments = max(0, _env_int(\"SGLANG_DIFFUSION_BCG_MAX_SEGMENTS\", 512))\n\n    def __getattr__(self, name: str) -> Any:\n        # Only reached for attributes the runner itself does not define; proxy\n        # them to the wrapped transformer so callers can treat the runner as a\n        # transparent stand-in. Use __dict__ to avoid recursing through\n        # __getattr__ before ``transformer`` is assigned in __init__.\n        try:\n            transformer = self.__dict__[\"transformer\"]\n        except KeyError as e:  # pragma: no cover - during/ before __init__\n            raise AttributeError(name) from e\n        return getattr(transformer, name)\n\n    # ------------------------------------------------------------------ #\n    # Public capture / replay API\n    # ------------------------------------------------------------------ #\n    @torch.no_grad()\n    def capture(self, **kwargs) -> bool:\n        \"\"\"Capture a graph for ``kwargs``'s signature if not already captured.\n\n        Idempotent: returns ``True`` when a graph is available for the\n        signature afterwards (already captured or newly captured), ``False``\n        when capture is disabled/blocked or failed (the caller then runs eager).\n        \"\"\"\n        if self._disabled_reason is not None:\n            return False\n        key = self._signature(kwargs)\n        if key in self._blocked:\n            return False","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/breakable_cuda_graph/runner.py#L235-L271","documentation":"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.","triggerScenarios":"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__.","commonSituations":"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.","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."],"exampleFix":"// before\nclass MyRunner(BreakableCudaGraphRunner):\n    def __init__(self):\n        self.debug_flag = self.enable_debug  # hits __getattr__ pre-init\n        super().__init__(...)\n// after\nclass MyRunner(BreakableCudaGraphRunner):\n    def __init__(self):\n        super().__init__(...)\n        self.debug_flag = self.enable_debug","handlingStrategy":"validation","validationCode":"runner = BreakableCudaGraphRunner(...)\nattr = getattr(runner, \"some_attr\", None)\nif attr is None and \"transformer\" in runner.__dict__:\n    attr = getattr(runner.transformer, \"some_attr\")","typeGuard":"def runner_ready(runner) -> bool:\n    return \"transformer\" in runner.__dict__","tryCatchPattern":"try:\n    val = runner.some_attr\nexcept AttributeError:\n    if \"transformer\" not in runner.__dict__:\n        logger.error(\"runner not initialized; original __init__ likely failed\")\n    raise","preventionTips":["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."],"tags":["attribute-access","partial-initialization","cuda-graph","wrapper"],"backgroundTag":"attributeerror-during-init","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}