{"record":{"id":"d80fb08d3e83ba98","repo":"HumanSignal/label-studio","slug":"exc-kwargs-report","errorCode":null,"errorMessage":"exc.kwargs['report']","messagePattern":"exc\\.kwargs\\['report'\\]","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"label_studio/io_storages/s3/serializers.py","lineNumber":33,"sourceCode":"logger = logging.getLogger(__name__)\n\n\nclass S3StorageSerializerMixin:\n    secure_fields = ['aws_access_key_id', 'aws_secret_access_key']\n\n    def to_representation(self, instance):\n        result = super().to_representation(instance)\n        for attr in self.secure_fields:\n            result.pop(attr)\n        return result\n\n    def validate_bucket(self, value):\n        if not value:\n            return value\n        try:\n            validate_bucket_name({'Bucket': value})\n        except ParamValidationError as exc:\n            raise ValidationError(exc.kwargs['report']) from exc\n        return value\n\n    def validate(self, data):\n        data = super().validate(data)\n        if not data.get('bucket', None):\n            return data\n\n        storage = self.instance\n        if storage:\n            for key, value in data.items():\n                setattr(storage, key, value)\n        else:\n            if 'id' in self.initial_data:\n                storage_object = self.Meta.model.objects.get(id=self.initial_data['id'])\n                for attr in self.secure_fields:\n                    data[attr] = data.get(attr) or getattr(storage_object, attr)\n            storage = self.Meta.model(**data)\n        try:","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/io_storages/s3/serializers.py#L15-L51","documentation":"S3StorageSerializerMixin.validate_bucket() runs boto3's validate_bucket_name on the submitted bucket. If the value fails boto3's client-side parameter validation, a botocore ParamValidationError carrying a human-readable `report` is converted into a DRF ValidationError with that report text. It fires before any network call.","triggerScenarios":"Submitting an S3 storage create/update request whose `bucket` field violates S3 naming rules (empty after strip, uppercase, invalid characters, too long, leading/trailing dots/dashes).","commonSituations":"Pasting a full s3://bucket/path URL into the bucket field; bucket names with underscores or uppercase from older setups; accidental whitespace; env-substitution leaving a placeholder like ${BUCKET}.","solutions":["Send only the bare bucket name (3–63 chars, lowercase letters, numbers, dots/hyphens) in the `bucket` field.","Strip any s3:// scheme or path from the value before submitting.","Pre-validate the name with botocore's validate_bucket_name in your client code."],"exampleFix":"// before\n{\"bucket\": \"s3://My_Bucket/data\"}\n\n// after\n{\"bucket\": \"my-bucket\"}","handlingStrategy":"validation","validationCode":"import re\n\nBUCKET_RE = re.compile(r'^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$')\n\ndef valid_bucket_name(name: str) -> bool:\n    return bool(name) and bool(BUCKET_RE.match(name)) and '..' not in name\n\nif not valid_bucket_name(payload['bucket']):\n    raise ValueError('bucket must be 3-63 chars, lowercase letters/numbers/dots/hyphens')","typeGuard":"def is_bare_bucket_name(value: str) -> bool:\n    return isinstance(value, str) and not value.startswith('s3://') and '/' not in value","tryCatchPattern":"try:\n    serializer.is_valid(raise_exception=True)\nexcept ValidationError as e:\n    # e.detail carries the botocore report; fix the bucket field accordingly\n    logger.warning('Bucket name rejected: %s', e.detail)","preventionTips":["Send only the bare bucket name — never a full s3:// URL or path.","Validate names with botocore's validate_bucket_name in client-side forms.","Watch for env-substitution placeholders like ${BUCKET} leaking into payloads.","Strip whitespace before submitting."],"tags":["s3","aws","validation","serializer","bucket-name"],"backgroundTag":"invalid-bucket-name","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}