{"record":{"id":"4ffa1400b2c3fb60","repo":"HumanSignal/label-studio","slug":"self-url-scheme-self-bucket-self-prefix-no","errorCode":null,"errorMessage":"{self.url_scheme}://{self.bucket}/{self.prefix} not found.","messagePattern":"(.+?)://(.+?)/(.+?) not found\\.","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"label_studio/io_storages/s3/models.py","lineNumber":116,"sourceCode":"            self.validate_connection(client)\n        return client, s3.Bucket(self.bucket)\n\n    @catch_and_reraise_from_none\n    def validate_connection(self, client=None):\n        logger.debug('validate_connection')\n        if client is None:\n            client = self.get_client()\n        # TODO(jo): add check for write access for .*Export.* classes\n        is_export = 'Export' in self.__class__.__name__\n        if self.prefix:\n            logger.debug(\n                f'[Class {self.__class__.__name__}]: Test connection to bucket {self.bucket} with prefix {self.prefix} using ListObjectsV2 operation'\n            )\n            result = client.list_objects_v2(Bucket=self.bucket, Prefix=self.prefix, MaxKeys=1)\n            # We expect 1 key with the prefix for imports. For exports it's okay if there are 0 with the prefix.\n            expected_keycount = 0 if is_export else 1\n            if (keycount := result.get('KeyCount')) is None or keycount < expected_keycount:\n                raise KeyError(f'{self.url_scheme}://{self.bucket}/{self.prefix} not found.')\n        else:\n            logger.debug(\n                f'[Class {self.__class__.__name__}]: Test connection to bucket {self.bucket} using HeadBucket operation'\n            )\n            client.head_bucket(Bucket=self.bucket)\n\n    @property\n    def path_full(self):\n        prefix = self.prefix or ''\n        return f'{self.url_scheme}://{self.bucket}/{prefix}'\n\n    @property\n    def type_full(self):\n        return 'Amazon AWS S3'\n\n    @catch_and_reraise_from_none\n    def get_bytes_stream(self, uri, range_header=None):\n        \"\"\"Get file directly from S3 using iter_chunks without wrapper.","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/io_storages/s3/models.py#L98-L134","documentation":"S3Storage.validate_connection() tests the bucket with ListObjectsV2 (MaxKeys=1) when a prefix is set. For imports it expects at least one key under bucket/prefix; if KeyCount is 0 (or missing) it raises KeyError('<scheme>://<bucket>/<prefix> not found.'). This means the bucket exists but contains no objects under that prefix (or the prefix is misspelled).","triggerScenarios":"Creating/updating an S3 import storage via validate() with a `prefix` that matches zero objects; also reachable through get_client_and_bucket when prefix-based validation runs.","commonSituations":"Typo in prefix or bucket; files stored without the expected prefix (e.g. uploaded to bucket root while prefix='data/'); region mismatch returning empty listings; bucket actually empty at connect time; export storages are exempt (expected count 0).","solutions":["Verify the bucket actually contains objects under the given prefix (aws s3 ls s3://<bucket>/<prefix>/).","Correct the `prefix` field in the storage config, or clear it if objects live at the bucket root.","Check region/endpoint config so ListObjectsV2 queries the right bucket.","If the bucket is intentionally empty, connect after uploading files or use an export storage."],"exampleFix":"// before\n{\"type\": \"s3\", \"bucket\": \"my-tasks\", \"prefix\": \"taskz/\"}   // typo\n\n// after\n{\"type\": \"s3\", \"bucket\": \"my-tasks\", \"prefix\": \"tasks/\"}","handlingStrategy":"validation","validationCode":"import boto3\n\ndef prefix_has_objects(bucket: str, prefix: str, **client_kwargs) -> bool:\n    s3 = boto3.client('s3', **client_kwargs)\n    resp = s3.list_objects_v2(Bucket=bucket, Prefix=prefix, MaxKeys=1)\n    return resp.get('KeyCount', 0) >= 1\n\n# run before creating the storage\nassert prefix_has_objects('my-bucket', 'tasks/')","typeGuard":"def has_valid_prefix(storage: dict) -> bool:\n    return isinstance(storage.get('prefix', ''), str)","tryCatchPattern":"try:\n    storage.save()\nexcept KeyError as e:\n    if 'not found' in str(e):\n        print(f'{bucket}/{prefix} has no objects; fix prefix or upload files')","preventionTips":["Run `aws s3 ls s3://bucket/prefix/` before wiring the storage.","Keep prefixes trailing-slash consistent ('tasks/' vs 'tasks').","Confirm region/endpoint so listings target the right bucket.","For export-only storages remember empty prefixes are acceptable; for imports they are not."],"tags":["s3","aws","storage","not-found"],"backgroundTag":"s3-prefix-not-found","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}