HumanSignal/label-studio · error · ValidationError

Wrong credentials for S3 {bucket_name}

Error message

Wrong credentials for S3 {bucket_name}

What it means

In S3StorageSerializerMixin.validate(), after building the storage object, validate_connection() is called; if it raises a botocore ParamValidationError the serializer raises ValidationError('Wrong credentials for S3 {bucket_name}'). Note the message is a plain .format() on a literal not containing braces placement for the value, so the rendered text keeps the literal '{bucket_name}'. It signals malformed/insufficient AWS parameters rather than an auth rejection from AWS.

Source

Thrown at label_studio/io_storages/s3/serializers.py:54

    def validate(self, data):
        data = super().validate(data)
        if not data.get('bucket', None):
            return data

        storage = self.instance
        if storage:
            for key, value in data.items():
                setattr(storage, key, value)
        else:
            if 'id' in self.initial_data:
                storage_object = self.Meta.model.objects.get(id=self.initial_data['id'])
                for attr in self.secure_fields:
                    data[attr] = data.get(attr) or getattr(storage_object, attr)
            storage = self.Meta.model(**data)
        try:
            storage.validate_connection()
        except ParamValidationError:
            raise ValidationError('Wrong credentials for S3 {bucket_name}'.format(bucket_name=storage.bucket))
        except ClientError as e:
            if (
                e.response.get('Error').get('Code') in ['SignatureDoesNotMatch', '403']
                or e.response.get('ResponseMetadata').get('HTTPStatusCode') == 403
            ):
                raise ValidationError(
                    'Cannot connect to S3 {bucket_name} with specified AWS credentials'.format(
                        bucket_name=storage.bucket
                    )
                )
            if (
                e.response.get('Error').get('Code') in ['NoSuchBucket', '404']
                or e.response.get('ResponseMetadata').get('HTTPStatusCode') == 404
            ):
                raise ValidationError('Cannot find bucket {bucket_name} in S3'.format(bucket_name=storage.bucket))
        except TypeError as e:
            logger.info(f'It seems access keys are incorrect: {e}', exc_info=True)
            raise ValidationError('It seems access keys are incorrect')

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Provide valid AWS credentials (aws_access_key_id / aws_secret_access_key / security_token) or rely on a correctly configured instance role.
  2. If using secure_mode updates, ensure stored secure fields actually exist on the existing storage_object.
  3. Set the correct region_name so the boto3 client can be constructed.
  4. Check the server log for the underlying ParamValidationError report for the exact bad parameter.

Example fix

// before
{"bucket": "my-bucket", "aws_access_key_id": "", "aws_secret_access_key": null}

// after
{"bucket": "my-bucket", "aws_access_key_id": "AKIA...", "aws_secret_access_key": "secret", "region_name": "us-east-1"}
Defensive patterns

Strategy: validation

Validate before calling

import os

def aws_credentials_present() -> bool:
    return all([
        os.environ.get('AWS_ACCESS_KEY_ID'),
        os.environ.get('AWS_SECRET_ACCESS_KEY'),
        os.environ.get('AWS_REGION') or os.environ.get('AWS_DEFAULT_REGION'),
    ])

if not aws_credentials_present():
    raise ValueError('Set AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_REGION first')

Type guard

def has_credential_fields(data: dict) -> bool:
    keys = ('aws_access_key_id', 'aws_secret_access_key', 'region_name')
    return any(isinstance(data.get(k), str) and data[k] for k in keys)

Try / catch

try:
    serializer.is_valid(raise_exception=True)
except ValidationError as e:
    if 'Wrong credentials for S3' in str(e.detail):
        # underlying ParamValidationError: check which AWS param was None/invalid
        logger.warning('S3 param validation failed for %s; check keys/region', bucket)

Prevention

When it happens

Trigger: storage.validate_connection() raising ParamValidationError during serializer validation — e.g. missing or wrong-typed aws_access_key_id/aws_secret_access_key/region/bucket parameters, often because secure_mode merges undefined attrs into None.

Common situations: Empty AWS keys in env (None passed to boto3 client); secure_mode storage update omitting credential fields so they resolve to None; region unset so client construction fails validation; expired/rotated keys removed from settings.

Related errors


AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29). Data as JSON: /api/errors/82f08f7f320128ab. Report an issue: GitHub.