{"record":{"id":"25c374453f72f6a5","repo":"infiniflow/ragflow","slug":"amazon-s3","errorCode":null,"errorMessage":"Amazon S3","messagePattern":"Amazon S3","errorType":"validation","errorClass":"ConnectorMissingCredentialError","httpStatus":null,"severity":"critical","filePath":"common/data_source/blob_connector.py","lineNumber":93,"sourceCode":"        \"\"\"Set whether to process images\"\"\"\n        logging.info(f\"Setting allow_images to {allow_images}.\")\n        self._allow_images = allow_images\n\n    def load_credentials(self, credentials: dict[str, Any]) -> dict[str, Any] | None:\n        \"\"\"Load credentials\"\"\"\n        logging.debug(f\"Loading credentials for {self.bucket_name} of type {self.bucket_type}\")\n\n        # Validate credentials\n        if self.bucket_type == BlobType.R2:\n            if not all(credentials.get(key) for key in [\"r2_access_key_id\", \"r2_secret_access_key\", \"account_id\"]):\n                raise ConnectorMissingCredentialError(\"Cloudflare R2\")\n\n        elif self.bucket_type == BlobType.S3:\n            authentication_method = credentials.get(\"authentication_method\", \"access_key\")\n\n            if authentication_method == \"access_key\":\n                if not all(credentials.get(key) for key in [\"aws_access_key_id\", \"aws_secret_access_key\"]):\n                    raise ConnectorMissingCredentialError(\"Amazon S3\")\n\n            elif authentication_method == \"iam_role\":\n                if not credentials.get(\"aws_role_arn\"):\n                    raise ConnectorMissingCredentialError(\"Amazon S3 IAM role ARN is required\")\n\n            elif authentication_method == \"assume_role\":\n                pass\n\n            else:\n                raise ConnectorMissingCredentialError(\"Unsupported S3 authentication method\")\n\n        elif self.bucket_type == BlobType.GOOGLE_CLOUD_STORAGE:\n            if not all(credentials.get(key) for key in [\"access_key_id\", \"secret_access_key\"]):\n                raise ConnectorMissingCredentialError(\"Google Cloud Storage\")\n\n        elif self.bucket_type == BlobType.OCI_STORAGE:\n            if not all(credentials.get(key) for key in [\"namespace\", \"region\", \"access_key_id\", \"secret_access_key\"]):\n                raise ConnectorMissingCredentialError(\"Oracle Cloud Infrastructure\")","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/blob_connector.py#L75-L111","documentation":"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.","triggerScenarios":"S3 connector config missing either key, or with authentication_method unset (defaults to access_key) while assuming IAM-instance credentials.","commonSituations":"Deployments meant to use instance roles but config defaults to access_key; expired rotated keys removed from secrets store; key naming drift (accessKeyId camelCase).","solutions":["Provide both aws_access_key_id and aws_secret_access_key","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)","Verify values are non-empty strings after secrets injection"],"exampleFix":"// before\ncreds = {\"aws_access_key_id\": \"AKIA...\"}  # secret missing\n\n// after\ncreds = {\"aws_access_key_id\": \"AKIA...\", \"aws_secret_access_key\": \"wJal...\"}","handlingStrategy":"validation","validationCode":"if creds.get(\"authentication_method\", \"access_key\") == \"access_key\":\n    if not (creds.get(\"aws_access_key_id\") and creds.get(\"aws_secret_access_key\")):\n        raise ValueError(\"access_key auth requires aws_access_key_id and aws_secret_access_key\")","typeGuard":"def is_s3_access_key_cred(x) -> bool:\n    \"\"\"True when x carries a complete S3 access-key pair for access_key auth.\"\"\"\n    return (\n        isinstance(x, dict)\n        and x.get(\"authentication_method\", \"access_key\") == \"access_key\"\n        and isinstance(x.get(\"aws_access_key_id\"), str) and x[\"aws_access_key_id\"].strip() != \"\"\n        and isinstance(x.get(\"aws_secret_access_key\"), str) and x[\"aws_secret_access_key\"].strip() != \"\"\n    )","tryCatchPattern":"try:\n    blob.load_credentials(creds)\nexcept ConnectorMissingCredentialError as e:\n    if \"Amazon S3\" in str(e):\n        if creds.get(\"authentication_method\", \"access_key\") == \"access_key\":\n            creds = fetch_rotated_aws_keys(); blob.load_credentials(creds)\n        else:\n            raise","preventionTips":["When running on EC2/ECS/EKS prefer iam_role auth and set the method explicitly","After key rotation, update both id and secret atomically in the secrets store","Never leave authentication_method implicit when you rely on non-default auth"],"tags":["amazon-s3","credentials","configuration","blob-storage"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}