infiniflow/ragflow · error · CredentialExpiredError

Provided blob storage credentials appear invalid or expired.

Error message

Provided blob storage credentials appear invalid or expired.

What it means

Raised by BlobStorageConnector.validate_connector_settings when the probe request fails with error code InvalidAccessKeyId, or SignatureDoesNotMatch with a 401, i.e. the credentials themselves are bad rather than merely under-permissioned. SignatureDoesNotMatch means the secret does not match the access key id; InvalidAccessKeyId means the access key id does not exist (or was rotated/deleted). Wrapped as CredentialExpiredError with a 'invalid or expired' message.

Source

Thrown at common/data_source/blob_connector.py:335

        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"),
    }

    # Initialize connector
    connector = BlobStorageConnector(

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Re-enter the access key id and secret exactly, with no leading/trailing whitespace or newlines
  2. If the key was rotated or deleted, generate a new pair and update the connector credential config
  3. Verify with a direct CLI test: aws s3 ls s3://<bucket> --endpoint-url <ep> using the same credentials
  4. Confirm the key pair belongs to the same account/tenancy as the bucket

Example fix

# before
creds = {
    'aws_access_key_id': 'AKIA...\n',   # trailing newline from a file read
    'aws_secret_access_key': secret,
}
# after
creds = {
    'aws_access_key_id': open(key_file).read().strip(),
    'aws_secret_access_key': open(sec_file).read().strip(),
}
Defensive patterns

Strategy: try-catch

Validate before calling

key = credentials['aws_access_key_id'].strip()
secret = credentials['aws_secret_access_key'].strip()
assert key and secret and '\n' not in secret, 'credential fields must be non-empty and whitespace-clean'
import boto3
boto3.client('s3', aws_access_key_id=key, aws_secret_access_key=secret).list_buckets()  # cheap auth probe

Try / catch

from common.data_source.exceptions import CredentialExpiredError
try:
    connector.validate_connector_settings()
except CredentialExpiredError as e:
    if 'invalid or expired' in str(e):
        prompt_reenter_credentials()  # non-retryable until user acts
    raise

Prevention

When it happens

Trigger: list_objects_v2 probe returning SignatureDoesNotMatch (wrong secret for the key id, or a copy/paste with trailing whitespace), or InvalidAccessKeyId not accompanied by 403/AccessDenied (deleted or rotated access key). Also hit when an OCI/GCS S3-compatible secret key was regenerated but the old one is still configured.

Common situations: Access key rotated by an admin and the connector config still holds the old pair; whitespace or newline contamination when pasting secrets; using an S3-compatible provider's console key after deleting it; environment drift between environments (prod secret copied to staging with a different key id).

Related errors


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