{"record":{"id":"1e113eb7e3ef1c5d","repo":"infiniflow/ragflow","slug":"amazon-s3-iam-role-arn-is-required","errorCode":null,"errorMessage":"Amazon S3 IAM role ARN is required","messagePattern":"Amazon S3 IAM role ARN is required","errorType":"validation","errorClass":"ConnectorMissingCredentialError","httpStatus":null,"severity":"critical","filePath":"common/data_source/blob_connector.py","lineNumber":97,"sourceCode":"    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\")\n\n        elif self.bucket_type == BlobType.S3_COMPATIBLE:\n            if not all(credentials.get(key) for key in [\"endpoint_url\", \"aws_access_key_id\", \"aws_secret_access_key\", \"addressing_style\"]):\n                raise ConnectorMissingCredentialError(\"S3 Compatible Storage\")","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/blob_connector.py#L79-L115","documentation":"When authentication_method='iam_role', the connector requires a non-empty aws_role_arn to assume; its absence raises ConnectorMissingCredentialError with message 'Amazon S3 IAM role ARN is required'.","triggerScenarios":"S3 config selecting iam_role auth but no role ARN supplied (empty/None aws_role_arn).","commonSituations":"Copying an access-key config and flipping only the method field; role ARN stored under a different key; forgot to create the IAM role.","solutions":["Set aws_role_arn to the full role ARN, e.g. arn:aws:iam::123456789012:role/MyS3Role","Ensure the runtime identity (instance/task profile) is allowed to sts:AssumeRole that role","Confirm the role's trust policy and S3 permissions"],"exampleFix":"// before\ncreds = {\"authentication_method\": \"iam_role\"}\n\n// after\ncreds = {\"authentication_method\": \"iam_role\", \"aws_role_arn\": \"arn:aws:iam::123456789012:role/MyS3Role\"}","handlingStrategy":"validation","validationCode":"if creds.get(\"authentication_method\") == \"iam_role\":\n    arn = creds.get(\"aws_role_arn\") or \"\"\n    if not arn.startswith(\"arn:aws:iam::\"):\n        raise ValueError(f\"aws_role_arn missing or malformed: {arn!r}\")","typeGuard":"def is_valid_role_arn(s: str) -> bool:\n    \"\"\"True for strings shaped like arn:aws:iam::<account>:role/<name>.\"\"\"\n    return isinstance(s, str) and s.startswith(\"arn:aws:iam::\") and \":role/\" in s and len(s.split(\":role/\", 1)[1]) > 0","tryCatchPattern":"try:\n    blob.load_credentials(creds)\nexcept ConnectorMissingCredentialError as e:\n    if \"IAM role ARN\" in str(e):\n        creds[\"aws_role_arn\"] = discover_task_role_arn()  # from instance metadata if applicable\n        blob.load_credentials(creds)","preventionTips":["Create and name the IAM role before selecting iam_role auth","Validate ARN format at config-save time","Ensure the runtime identity's trust policy allows assuming the role"],"tags":["amazon-s3","iam","credentials","configuration"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}