{"record":{"id":"9138d681877e8fd4","repo":"apache/beam","slug":"type-self-name-not-registered-as-specifiable-decorate-type","errorCode":null,"errorMessage":"'{type(self).__name__}' not registered as Specifiable. Decorate ({type(self).__name__}) with @specifiable","messagePattern":"'(.+?)' not registered as Specifiable\\. Decorate \\((.+?)\\) with @specifiable","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/ml/anomaly/specifiable.py","lineNumber":198,"sourceCode":"      return subclass\n\n    kwargs = {\n        k: _specifiable_from_spec_helper(v, _run_init)\n        for k, v in spec.config.items()\n    }\n\n    if _run_init:\n      kwargs[\"_run_init\"] = True\n    return subclass(**kwargs)\n\n  def to_spec(self) -> Spec:\n    \"\"\"Generate a spec from a `Specifiable` subclass object.\n\n    Returns:\n      Spec: The specification of the instance.\n    \"\"\"\n    if getattr(type(self), 'spec_type', None) is None:\n      raise ValueError(\n          f\"'{type(self).__name__}' not registered as Specifiable. \"\n          f\"Decorate ({type(self).__name__}) with @specifiable\")\n\n    args = {\n        k: _specifiable_to_spec_helper(v)\n        for k, v in self.init_kwargs.items()\n    }\n\n    return Spec(type=self.spec_type(), config=args)\n\n  def run_original_init(self) -> None:\n    \"\"\"Invoke the original __init__ method with original keyword arguments\"\"\"\n    pass\n\n  @classmethod\n  def unspecifiable(cls) -> None:\n    \"\"\"Resume the class structure prior to specifiable\"\"\"\n    pass","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/ml/anomaly/specifiable.py#L180-L216","documentation":"apache_beam.ml.anomaly.specifiable.to_spec() can only serialize objects whose class was registered via the @specifiable decorator, which sets a class-level `spec_type`. If the class lacks `spec_type`, the library cannot map the instance back to a constructor spec and raises this ValueError.","triggerScenarios":"Calling to_spec() (or specifiable_object_to_spec) on an instance of a class not decorated with @specifiable, e.g. a custom AnomalyDetector subclass or a third-party sklearn model passed into ML Transform without registration.","commonSituations":"Users write a custom detector subclass and pass it to RunInference/anomaly transforms without decorating it; upgrading Beam adds @specifiable to internal classes that user subclasses now shadow; passing plain sklearn/torch objects inside ensemble detectors.","solutions":["Decorate the class with @specifiable (optionally @specifiable(spec_type='my_type')) before instantiating/calling to_spec","If you cannot modify the class, wrap it in a Specifiable-compatible adapter class decorated with @specifiable","Check that the instance's actual (most-derived) class is the decorated one, not an undecorated subclass"],"exampleFix":"// before\nclass MyDetector(AnomalyDetector):\n    ...\nobj.to_spec()\n\n// after\nfrom apache_beam.ml.anomaly import specifiable\n\n@specifiable.specifiable\nclass MyDetector(AnomalyDetector):\n    ...\nobj.to_spec()","handlingStrategy":"validation","validationCode":"from apache_beam.ml.anomaly import specifiable\nif getattr(type(detector), 'spec_type', None) is None:\n    raise TypeError(f\"{type(detector).__name__} must be decorated with @specifiable before to_spec()\")","typeGuard":"def is_specifiable(obj) -> bool:\n    return getattr(type(obj), 'spec_type', None) is not None","tryCatchPattern":null,"preventionTips":["Always decorate custom detector/transform classes with @specifiable","Run a unit test that calls to_spec() on every pipeline component","Keep custom class names unique from Beam built-ins"],"tags":["python","apache-beam","serialization","registration"],"backgroundTag":"class-not-found","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}