infiniflow/ragflow · error · ConnectorMissingCredentialError

Blob storage credentials not loaded.

Error message

Blob storage credentials not loaded.

What it means

Raised by BlobStorageConnector.validate_connector_settings as the first guard: if self.s3_client is None the credentials were never loaded (load_credentials not called or failed), so validation cannot proceed and ConnectorMissingCredentialError('Blob storage credentials not loaded.') is raised. Unlike the generic 'Blob storage' message elsewhere, this one explicitly says credentials were not loaded.

Source

Thrown at common/data_source/blob_connector.py:313

            start=datetime(1970, 1, 1, tzinfo=timezone.utc),
            end=datetime.now(timezone.utc),
        )

    def poll_source(self, start: SecondsSinceUnixEpoch, end: SecondsSinceUnixEpoch) -> GenerateDocumentsOutput:
        """Poll source to get documents"""
        if self.s3_client is None:
            raise ConnectorMissingCredentialError("Blob storage")

        start_datetime = datetime.fromtimestamp(start, tz=timezone.utc)
        end_datetime = datetime.fromtimestamp(end, tz=timezone.utc)

        for batch in self._yield_blob_objects(start_datetime, end_datetime):
            yield batch

    def validate_connector_settings(self) -> None:
        """Validate connector settings"""
        if self.s3_client is None:
            raise ConnectorMissingCredentialError("Blob storage credentials not loaded.")

        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",
            ]:

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Call load_credentials(credentials) successfully before validate_connector_settings()
  2. Check that the credentials dict has all keys required for your bucket_type (they are validated with truthiness, so blank strings count as missing)
  3. In a UI/preflight context, surface this error as 'enter credentials first' rather than a connection failure
  4. Fix ordering in orchestrators: load_credentials -> validate_connector_settings -> poll/list

Example fix

// before
connector = BlobStorageConnector(bucket_type='oci', bucket_name='docs')
connector.validate_connector_settings()  # raises
// after
connector = BlobStorageConnector(bucket_type='oci', bucket_name='docs')
connector.load_credentials({
    'namespace': ns, 'region': r,
    'access_key_id': k, 'secret_access_key': s,
})
connector.validate_connector_settings()
Defensive patterns

Strategy: validation

Validate before calling

if connector.s3_client is None:
    return 'MISSING_CREDENTIALS'  # ask user for credentials, do not probe
connector.validate_connector_settings()

Type guard

def has_loaded_client(c: BlobStorageConnector) -> bool:
    return c.s3_client is not None

Try / catch

try:
    connector.validate_connector_settings()
except ConnectorMissingCredentialError:
    report_to_user('Enter blob storage credentials, then re-test the connection')

Prevention

When it happens

Trigger: Calling validate_connector_settings() on a fresh connector, or after a load_credentials attempt that raised before create_s3_client ran. This is typically the preflight check an indexing backend runs before accepting a connector configuration.

Common situations: UI 'Test connection'/preflight flow invoked before the user entered credentials; credential provider returned None/empty dict; ordering bug in orchestration where validation runs before credential loading.

Related errors


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