{"record":{"id":"bc4f7d84be0d6c10","repo":"sgl-project/sglang","slug":"subclass-self-class-name-must-define-su-bc4f7d","errorCode":null,"errorMessage":"Subclass {self.__class__.__name__} must define _supported_attention_backends","messagePattern":"Subclass (.+?) must define _supported_attention_backends","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/models/encoders/base.py","lineNumber":226,"sourceCode":"    ]\n    _fsdp_shard_conditions: list = field(default_factory=lambda: [])\n    # Methods that drive a forward pass without going through __call__. FSDP2\n    # only unshards around the wrapped module's own forward, so anything the\n    # shard conditions left in the root group stays sharded unless the entry\n    # point is registered; loaders read this and register each name.\n    _fsdp_forward_methods: tuple[str, ...] = ()\n    _stacked_params_mapping: list[tuple[str, str, str]] = field(default_factory=list)\n    _supported_attention_backends: set[AttentionBackendEnum] = (\n        TextEncoderConfig()._supported_attention_backends\n    )\n\n    def __init__(self, config: TextEncoderConfig) -> None:\n        super().__init__()\n        self.config = config\n        self._fsdp_shard_conditions = config.arch_config._fsdp_shard_conditions\n        self._stacked_params_mapping = config.arch_config.stacked_params_mapping\n        if not self.supported_attention_backends:\n            raise ValueError(\n                f\"Subclass {self.__class__.__name__} must define _supported_attention_backends\"\n            )\n\n    @abstractmethod\n    def forward(\n        self,\n        input_ids: torch.Tensor | None,\n        position_ids: torch.Tensor | None = None,\n        attention_mask: torch.Tensor | None = None,\n        inputs_embeds: torch.Tensor | None = None,\n        output_hidden_states: bool | None = None,\n        **kwargs,\n    ) -> BaseEncoderOutput:\n        pass\n\n    @property\n    def supported_attention_backends(self) -> set[AttentionBackendEnum]:\n        return self._supported_attention_backends","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/models/encoders/base.py#L208-L244","documentation":"Raised by the text encoder base __init__ when the subclass's supported_attention_backends (from _supported_attention_backends) is empty. Every text encoder must declare which attention backends it supports; omitting it is an implementation error caught at construction.","triggerScenarios":"Subclassing the base text encoder without defining _supported_attention_backends (or defining it as an empty list) and instantiating the subclass.","commonSituations":"Adding a new text encoder model class and forgetting the backend declaration required by the base class contract.","solutions":["Define _supported_attention_backends = ['flashattention', 'fa3', ...] (non-empty) on your subclass","Copy the declaration pattern from an existing encoder subclass"],"exampleFix":"# before\nclass MyEncoder(BaseTextEncoder):\n    _supported_attention_backends: list[str] = []\n# after\nclass MyEncoder(BaseTextEncoder):\n    _supported_attention_backends = [\"flashattention\", \"triton_attn\"]","handlingStrategy":"validation","validationCode":"assert getattr(MyEncoder, \"supported_attention_backends\", None), \"declare _supported_attention_backends\"","typeGuard":"def declares_backends(cls) -> bool:\n    return bool(getattr(cls, \"_supported_attention_backends\", None))","tryCatchPattern":null,"preventionTips":["When adding a new encoder, copy the backend declaration from an existing subclass first"],"tags":["encoder","subclass-contract","attention-backend"],"backgroundTag":"missing-implementation","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}