infiniflow/ragflow · error · InsufficientPermissionsError

Insufficient permissions to list objects in bucket '{self.bu

Error message

Insufficient permissions to list objects in bucket '{self.bucket_name}'. Please check your bucket policy and/or IAM policy.

What it means

Raised by BlobStorageConnector.validate_connector_settings when the list_objects_v2 probe fails with error code AccessDenied, InvalidAccessKeyId, or SignatureDoesNotMatch AND (status 403 or code == 'AccessDenied'). This branch means the credentials authenticated but the identity lacks s3:ListBucket permission on the bucket, so InsufficientPermissionsError is raised with guidance to check bucket and IAM policy.

Source

Thrown at common/data_source/blob_connector.py:333

        if not self.bucket_name:
            raise ConnectorValidationError("No bucket name was provided in connector settings.")

        try:
            # Lightweight validation step
            self.s3_client.list_objects_v2(Bucket=self.bucket_name, Prefix=self.prefix, MaxKeys=1)

        except Exception as e:
            error_code = getattr(e, "response", {}).get("Error", {}).get("Code", "")
            status_code = getattr(e, "response", {}).get("ResponseMetadata", {}).get("HTTPStatusCode")

            # Common S3 error scenarios
            if error_code in [
                "AccessDenied",
                "InvalidAccessKeyId",
                "SignatureDoesNotMatch",
            ]:
                if status_code == 403 or error_code == "AccessDenied":
                    raise InsufficientPermissionsError(f"Insufficient permissions to list objects in bucket '{self.bucket_name}'. Please check your bucket policy and/or IAM policy.")
                if status_code == 401 or error_code == "SignatureDoesNotMatch":
                    raise CredentialExpiredError("Provided blob storage credentials appear invalid or expired.")

                raise CredentialExpiredError(f"Credential issue encountered ({error_code}).")

            if error_code == "NoSuchBucket" or status_code == 404:
                raise ConnectorValidationError(f"Bucket '{self.bucket_name}' does not exist or cannot be found.")

            raise ConnectorValidationError(f"Unexpected S3 client error (code={error_code}, status={status_code}): {e}")


if __name__ == "__main__":
    # Example usage
    credentials_dict = {
        "aws_access_key_id": os.environ.get("AWS_ACCESS_KEY_ID"),
        "aws_secret_access_key": os.environ.get("AWS_SECRET_ACCESS_KEY"),
    }

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Add s3:ListBucket on the specific bucket (and s3:GetObject on bucket/*) to the IAM policy of the key's owner
  2. If the bucket is in another account, add a bucket-policy statement allowing s3:ListBucket for the caller's ARN
  3. Check for explicit Deny statements in IAM, bucket policy, SCPs, or VPC endpoint policies that override the Allow
  4. For S3-compatible stores, grant the key's policy the listing permission on the bucket (e.g. MinIO 'readlist' or console 'readwrite' scoped policy)

Example fix

# before (IAM policy — download only)
{
  "Effect": "Allow",
  "Action": ["s3:GetObject"],
  "Resource": ["arn:aws:s3:::docs-bucket/*"]
}
# after
{
  "Effect": "Allow",
  "Action": ["s3:GetObject"],
  "Resource": ["arn:aws:s3:::docs-bucket/*"]
},
{
  "Effect": "Allow",
  "Action": ["s3:ListBucket"],
  "Resource": ["arn:aws:s3:::docs-bucket"]
}
Defensive patterns

Strategy: try-catch

Validate before calling

import boto3
sts = boto3.client('sts', aws_access_key_id=k, aws_secret_access_key=s)
identity = sts.get_caller_identity()  # cheap auth check
# then verify ListBucket with an explicit dry probe:
s3 = boto3.client('s3', aws_access_key_id=k, aws_secret_access_key=s)
try:
    s3.list_objects_v2(Bucket=bucket, MaxKeys=1)
except s3.exceptions.ClientError as e:
    if e.response['Error']['Code'] in ('AccessDenied', '403'):
        raise PermissionError('need s3:ListBucket on ' + bucket) from e

Try / catch

from common.data_source.exceptions import InsufficientPermissionsError
try:
    connector.validate_connector_settings()
except InsufficientPermissionsError as e:
    alert_ops(f'IAM fix needed: {e}')  # non-retryable config problem
    raise

Prevention

When it happens

Trigger: An IAM user/role with GetObject but no ListBucket permission running validate_connector_settings; a bucket policy that explicitly denies s3:ListBucket for the caller's principal; an SCP or VPC endpoint policy restricting ListBucket; also AccessDenied from S3-compatible providers when the key is scoped to a different bucket.

Common situations: Least-privilege IAM keys created for read/download only; bucket owned by another AWS account with a bucket policy missing a ListBucket statement for the caller; MinIO/Ops role without read:list access; confusion between ListBucket (bucket-level) and GetObject (object-level) permissions.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/846efaae8e3eb645. Report an issue: GitHub.