{"record":{"id":"9216d749342d3e53","repo":"HumanSignal/label-studio","slug":"notimplementederror","errorCode":null,"errorMessage":"NotImplementedError","messagePattern":"NotImplementedError","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"label_studio/io_storages/base_models.py","lineNumber":330,"sourceCode":"    description = models.TextField(_('description'), null=True, blank=True, help_text='Cloud storage description')\n    created_at = models.DateTimeField(_('created at'), auto_now_add=True, help_text='Creation time')\n\n    synchronizable = models.BooleanField(_('synchronizable'), default=True, help_text='If storage can be synced')\n\n    def validate_connection(self, client=None):\n        raise NotImplementedError('validate_connection is not implemented')\n\n    class Meta:\n        abstract = True\n\n\nclass ImportStorage(Storage):\n    def iter_objects(self) -> Iterator[Any]:\n        \"\"\"\n        Returns:\n            Iterator[Any]: An iterator for objects in the storage.\n        \"\"\"\n        raise NotImplementedError\n\n    def iter_keys(self) -> Iterator[str]:\n        \"\"\"\n        Returns:\n            Iterator[str]: An iterator of keys for each object in the storage.\n        \"\"\"\n        raise NotImplementedError\n\n    def get_unified_metadata(self, obj: Any) -> dict:\n        \"\"\"\n        Args:\n            obj: The storage object to get metadata for\n        Returns:\n            dict: A dictionary of metadata for the object with keys:\n            'key', 'last_modified', 'size'.\n        \"\"\"\n        raise NotImplementedError\n","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/io_storages/base_models.py#L312-L348","documentation":"ImportStorage.iter_objects is the abstract hook a backend must implement to yield storage objects during a synchronization scan. The base class raises NotImplementedError, so calling it on a subclass without an override (or on the base class itself) always fails. It is invoked by ImportStorage.create / sync paths when linking tasks.","triggerScenarios":"Running a sync (_scan_and_create_links -> create -> iter_objects) on a custom ImportStorage subclass that does not implement iter_objects; instantiating ImportStorage directly and syncing.","commonSituations":"Custom storage integration missing the iter_objects method; refactoring moved the implementation into iter_keys only while the sync path still relies on iter_objects.","solutions":["Implement iter_objects in your ImportStorage subclass to yield objects (e.g. bucket object wrappers) from your backend.","If your backend is key-listing only, implement both iter_keys and iter_objects so either scan path works.","Verify the storage you synced is the concrete subclass (e.g. S3ImportStorage), not the abstract ImportStorage base."],"exampleFix":"// before\nclass MyImportStorage(ImportStorage):\n    pass\n\n// after\nclass MyImportStorage(ImportStorage):\n    def iter_objects(self):\n        for obj in self.client.list_objects():\n            yield obj","handlingStrategy":"validation","validationCode":"import inspect\nif inspect.isabstract(type(storage)) or type(storage).iter_objects is ImportStorage.iter_objects:\n    raise TypeError(f'{type(storage).__name__} does not implement iter_objects')","typeGuard":"def supports_object_iteration(storage) -> bool:\n    return type(storage).iter_objects is not ImportStorage.iter_objects","tryCatchPattern":"try:\n    for obj in storage.iter_objects():\n        process(obj)\nexcept NotImplementedError:\n    logger.error('%s cannot be synced: iter_objects not implemented', type(storage).__name__)","preventionTips":["Subclass a concrete backend (e.g. S3ImportStorage) rather than the abstract ImportStorage.","Implement all abstract iteration hooks in custom backends and cover them with a smoke sync test in CI.","Never instantiate or sync the abstract ImportStorage base directly."],"tags":["not-implemented","storage","subclassing","abstract-method"],"backgroundTag":"notimplemented-abstract-method","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}