{"record":{"id":"6d5333c9d1cc25de","repo":"infiniflow/ragflow","slug":"blob-storage-credentials-not-loaded","errorCode":null,"errorMessage":"Blob storage credentials not loaded.","messagePattern":"Blob storage credentials not loaded\\.","errorType":"validation","errorClass":"ConnectorMissingCredentialError","httpStatus":null,"severity":"error","filePath":"common/data_source/blob_connector.py","lineNumber":313,"sourceCode":"            start=datetime(1970, 1, 1, tzinfo=timezone.utc),\n            end=datetime.now(timezone.utc),\n        )\n\n    def poll_source(self, start: SecondsSinceUnixEpoch, end: SecondsSinceUnixEpoch) -> GenerateDocumentsOutput:\n        \"\"\"Poll source to get documents\"\"\"\n        if self.s3_client is None:\n            raise ConnectorMissingCredentialError(\"Blob storage\")\n\n        start_datetime = datetime.fromtimestamp(start, tz=timezone.utc)\n        end_datetime = datetime.fromtimestamp(end, tz=timezone.utc)\n\n        for batch in self._yield_blob_objects(start_datetime, end_datetime):\n            yield batch\n\n    def validate_connector_settings(self) -> None:\n        \"\"\"Validate connector settings\"\"\"\n        if self.s3_client is None:\n            raise ConnectorMissingCredentialError(\"Blob storage credentials not loaded.\")\n\n        if not self.bucket_name:\n            raise ConnectorValidationError(\"No bucket name was provided in connector settings.\")\n\n        try:\n            # Lightweight validation step\n            self.s3_client.list_objects_v2(Bucket=self.bucket_name, Prefix=self.prefix, MaxKeys=1)\n\n        except Exception as e:\n            error_code = getattr(e, \"response\", {}).get(\"Error\", {}).get(\"Code\", \"\")\n            status_code = getattr(e, \"response\", {}).get(\"ResponseMetadata\", {}).get(\"HTTPStatusCode\")\n\n            # Common S3 error scenarios\n            if error_code in [\n                \"AccessDenied\",\n                \"InvalidAccessKeyId\",\n                \"SignatureDoesNotMatch\",\n            ]:","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/blob_connector.py#L295-L331","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Call load_credentials(credentials) successfully before validate_connector_settings()","Check that the credentials dict has all keys required for your bucket_type (they are validated with truthiness, so blank strings count as missing)","In a UI/preflight context, surface this error as 'enter credentials first' rather than a connection failure","Fix ordering in orchestrators: load_credentials -> validate_connector_settings -> poll/list"],"exampleFix":"// before\nconnector = BlobStorageConnector(bucket_type='oci', bucket_name='docs')\nconnector.validate_connector_settings()  # raises\n// after\nconnector = BlobStorageConnector(bucket_type='oci', bucket_name='docs')\nconnector.load_credentials({\n    'namespace': ns, 'region': r,\n    'access_key_id': k, 'secret_access_key': s,\n})\nconnector.validate_connector_settings()","handlingStrategy":"validation","validationCode":"if connector.s3_client is None:\n    return 'MISSING_CREDENTIALS'  # ask user for credentials, do not probe\nconnector.validate_connector_settings()","typeGuard":"def has_loaded_client(c: BlobStorageConnector) -> bool:\n    return c.s3_client is not None","tryCatchPattern":"try:\n    connector.validate_connector_settings()\nexcept ConnectorMissingCredentialError:\n    report_to_user('Enter blob storage credentials, then re-test the connection')","preventionTips":["Order operations: load_credentials -> validate_connector_settings; enforce with one helper used everywhere","In preflight UIs, distinguish this 'not loaded' error from real validation failures so users get the right prompt"],"tags":["credentials","validation","lifecycle","blob-storage"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}