infiniflow/ragflow · critical · ConnectorMissingCredentialError

Amazon S3

Error message

Amazon S3

What it means

For S3 buckets with authentication_method='access_key' (the default), both aws_access_key_id and aws_secret_access_key must be present and non-empty; otherwise ConnectorMissingCredentialError('Amazon S3') is raised.

Source

Thrown at common/data_source/blob_connector.py:93

        """Set whether to process images"""
        logging.info(f"Setting allow_images to {allow_images}.")
        self._allow_images = allow_images

    def load_credentials(self, credentials: dict[str, Any]) -> dict[str, Any] | None:
        """Load credentials"""
        logging.debug(f"Loading credentials for {self.bucket_name} of type {self.bucket_type}")

        # Validate credentials
        if self.bucket_type == BlobType.R2:
            if not all(credentials.get(key) for key in ["r2_access_key_id", "r2_secret_access_key", "account_id"]):
                raise ConnectorMissingCredentialError("Cloudflare R2")

        elif self.bucket_type == BlobType.S3:
            authentication_method = credentials.get("authentication_method", "access_key")

            if authentication_method == "access_key":
                if not all(credentials.get(key) for key in ["aws_access_key_id", "aws_secret_access_key"]):
                    raise ConnectorMissingCredentialError("Amazon S3")

            elif authentication_method == "iam_role":
                if not credentials.get("aws_role_arn"):
                    raise ConnectorMissingCredentialError("Amazon S3 IAM role ARN is required")

            elif authentication_method == "assume_role":
                pass

            else:
                raise ConnectorMissingCredentialError("Unsupported S3 authentication method")

        elif self.bucket_type == BlobType.GOOGLE_CLOUD_STORAGE:
            if not all(credentials.get(key) for key in ["access_key_id", "secret_access_key"]):
                raise ConnectorMissingCredentialError("Google Cloud Storage")

        elif self.bucket_type == BlobType.OCI_STORAGE:
            if not all(credentials.get(key) for key in ["namespace", "region", "access_key_id", "secret_access_key"]):
                raise ConnectorMissingCredentialError("Oracle Cloud Infrastructure")

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Provide both aws_access_key_id and aws_secret_access_key
  2. If running on EC2/ECS/EKS with an instance role, set authentication_method='iam_role' with aws_role_arn (or ensure the method field is explicit)
  3. Verify values are non-empty strings after secrets injection

Example fix

// before
creds = {"aws_access_key_id": "AKIA..."}  # secret missing

// after
creds = {"aws_access_key_id": "AKIA...", "aws_secret_access_key": "wJal..."}
Defensive patterns

Strategy: validation

Validate before calling

if creds.get("authentication_method", "access_key") == "access_key":
    if not (creds.get("aws_access_key_id") and creds.get("aws_secret_access_key")):
        raise ValueError("access_key auth requires aws_access_key_id and aws_secret_access_key")

Type guard

def is_s3_access_key_cred(x) -> bool:
    """True when x carries a complete S3 access-key pair for access_key auth."""
    return (
        isinstance(x, dict)
        and x.get("authentication_method", "access_key") == "access_key"
        and isinstance(x.get("aws_access_key_id"), str) and x["aws_access_key_id"].strip() != ""
        and isinstance(x.get("aws_secret_access_key"), str) and x["aws_secret_access_key"].strip() != ""
    )

Try / catch

try:
    blob.load_credentials(creds)
except ConnectorMissingCredentialError as e:
    if "Amazon S3" in str(e):
        if creds.get("authentication_method", "access_key") == "access_key":
            creds = fetch_rotated_aws_keys(); blob.load_credentials(creds)
        else:
            raise

Prevention

When it happens

Trigger: S3 connector config missing either key, or with authentication_method unset (defaults to access_key) while assuming IAM-instance credentials.

Common situations: Deployments meant to use instance roles but config defaults to access_key; expired rotated keys removed from secrets store; key naming drift (accessKeyId camelCase).

Related errors


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