infiniflow/ragflow · error · ConnectorMissingCredentialError
Airtable credentials not loaded
Error message
Airtable credentials not loaded
What it means
ConnectorMissingCredentialError raised by AirtableConnector._iter_attachment_entries (common/data_source/airtable_connector.py:56-58). The connector stores its AirtableApi client in self._airtable_client, populated only when credentials are loaded; the attachment-scan generator guards on this and refuses to iterate when no client was ever set, rather than crashing later with an opaque AttributeError. The sister method load_from_state (line ~104) raises the identical error for the same reason.
Source
Thrown at common/data_source/airtable_connector.py:49
This connector ingests Airtable attachments as raw blobs without
parsing file content or generating text/image sections.
"""
def __init__(
self,
base_id: str,
table_name_or_id: str,
batch_size: int = INDEX_BATCH_SIZE,
) -> None:
self.base_id = base_id
self.table_name_or_id = table_name_or_id
self.batch_size = batch_size
self._airtable_client: AirtableApi | None = None
self.size_threshold = AIRTABLE_CONNECTOR_SIZE_THRESHOLD
def _iter_attachment_entries(self) -> Generator[tuple[str, str, str, str, str | None, dict[str, Any]], None, None]:
if not self._airtable_client:
raise ConnectorMissingCredentialError("Airtable credentials not loaded")
table = self.airtable_client.table(self.base_id, self.table_name_or_id)
records = table.all()
logging.info(f"Starting Airtable attachment scan for table {self.table_name_or_id}, {len(records)} records found.")
for record in records:
record_id = record.get("id")
fields = record.get("fields", {})
created_time = record.get("createdTime")
for field_value in fields.values():
if not isinstance(field_value, list):
continue
for attachment in field_value:
filename = attachment.get("filename")
attachment_id = attachment.get("id")View on GitHub (pinned to 554fb1133a)
Solutions
- Load/apply Airtable credentials (API key/personal access token) through the same code path the ingestion service uses before calling load_from_state.
- Check self._airtable_client (or the public airtable_client property) is non-None before starting the sync and surface a clear configuration error.
- If credentials come from the data-source record, verify that record actually contains the airtable token before scheduling the connector.
Example fix
# before conn = AirtableConnector(base_id, table) docs = conn.load_from_state() # raises # after conn = AirtableConnector(base_id, table) conn.load_credentials(credentials) # sets _airtable_client docs = conn.load_from_state()
Defensive patterns
Strategy: validation
Validate before calling
if connector._airtable_client is None:
raise RuntimeError("Airtable credentials not loaded — call the credential loader before scanning attachments") Type guard
def airtable_ready(connector) -> bool:
return connector._airtable_client is not None Try / catch
from common.data_source.airtable_connector import ConnectorMissingCredentialError
try:
entries = list(connector._iter_attachment_entries())
except ConnectorMissingCredentialError:
log.error("data source missing Airtable token; mark sync failed and notify")
raise Prevention
- Always run the connector's credential-loading step right after construction.
- Validate the data-source record contains an Airtable token before scheduling sync.
- In tests, inject a stub AirtableApi client into _airtable_client.
When it happens
Trigger: Calling load_from_state (or anything that drives _iter_attachment_entries) on an AirtableConnector that was constructed with only base_id/table_name_or_id but never had credentials applied (the credential-loading path that sets _airtable_client was skipped or failed silently).
Common situations: Building the connector directly in tests/scripts without the credential-loading step the production ingestion service performs; a data-source sync job whose credential fetch returned empty and the code proceeded to load anyway; connector reused after a credential reset.
Related errors
- Azure Blob: connection_string is required for the connection
- Azure Blob: account_name and account_key are required for th
- main() must be defined or exported.
- Invalid chat_id: ${payload.chat_id}
- main() must be defined or exported.
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/6a5f910a5623bdd4.
Report an issue: GitHub.