infiniflow/ragflow · error · RuntimeError

Credential item {name=} was not found

Error message

Credential item {name=} was not found

What it means

Raised by the nested get_or_raise helper inside ImapConnector._get_mail_client when the credentials dict has no value for _USERNAME_KEY or _PASSWORD_KEY (missing key, None, or empty string). It means load_credentials was never called, was called with an incomplete dict, or the dict keys do not match the expected names. It surfaces as a RuntimeError before any network activity.

Source

Thrown at common/data_source/imap_connector.py:204

        The `imaplib.IMAP4_SSL` object is supposed to be an "ephemeral" object; it's not something that you can login,
        logout, then log back into again. I.e., the following will fail:

        ```py
        mail_client.login(..)
        mail_client.logout();
        mail_client.login(..)
        ```

        Therefore, you need a fresh, new instance in order to operate with IMAP. This function gives one to you.

        # Notes
        This function will throw an error if the credentials have not yet been set.
        """

        def get_or_raise(name: str) -> str:
            value = self.credentials.get(name)
            if not value:
                raise RuntimeError(f"Credential item {name=} was not found")
            if not isinstance(value, str):
                raise RuntimeError(f"Credential item {name=} must be of type str, instead received {type(name)=}")
            return value

        username = get_or_raise(_USERNAME_KEY)
        password = get_or_raise(_PASSWORD_KEY)

        mail_client = imaplib.IMAP4_SSL(host=self._host, port=self._port)
        status, _data = mail_client.login(user=username, password=password)

        if status != _IMAP_OKAY_STATUS:
            raise RuntimeError(f"Failed to log into imap server; {status=}")

        return mail_client

    def _load_from_checkpoint(
        self,
        start: SecondsSinceUnixEpoch,

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Call load_credentials with both required keys (username and password) before any operation that opens a mail client.
  2. Inspect the exact keys expected (_USERNAME_KEY / _PASSWORD_KEY constants at the top of common/data_source/imap_connector.py) and align your dict names to them.
  3. If credentials come from a store, verify both fields were persisted for this user/instance and are non-empty strings.
  4. Add a startup assertion in your orchestration code that fails fast with a clear message before the connector runs.

Example fix

# before
connector = ImapConnector(host='imap.example.com', port=993, credentials={'username': 'a@b.com'})
docs = connector.load_from_checkpoint(start, end, checkpoint)  # RuntimeError: name='password' not found

# after
connector = ImapConnector(host='imap.example.com', port=993, credentials={'username': 'a@b.com', 'password': os.environ['IMAP_PASSWORD']})
docs = connector.load_from_checkpoint(start, end, checkpoint)
Defensive patterns

Strategy: validation

Validate before calling

def imap_credentials_complete(credentials: dict) -> bool:
    return all(
        isinstance(credentials.get(k), str) and credentials.get(k)
        for k in ('username', 'password')
    )

Type guard

from typing import Any

def has_str_credentials(creds: dict[str, Any], *keys: str) -> bool:
    return all(isinstance(creds.get(k), str) and creds[k].strip() for k in keys)

Try / catch

try:
    connector.load_from_checkpoint(start, end, checkpoint)
except RuntimeError as e:
    if 'was not found' in str(e):
        raise RuntimeError('IMAP credentials incomplete; re-run load_credentials with username+password') from e
    raise

Prevention

When it happens

Trigger: Calling _get_mail_client() (directly or via _load_from_checkpoint) on an ImapConnector whose credentials dict lacks the username or password entry - e.g. constructing the connector and immediately triggering a sync, or passing a dict with keys like 'user'/'pass' instead.

Common situations: Skipping the connector lifecycle load_credentials step; a credential refresh that rewrote the dict and dropped one field; per-user connector config saved with an empty password field in the UI.

Related errors


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