infiniflow/ragflow · error · RuntimeError
Credential item {name=} must be of type str, instead receive
Error message
Credential item {name=} must be of type str, instead received {type(name)=} What it means
Raised by the same get_or_raise helper when a credential value exists but is not a str (e.g. an int, dict, or list). Note that the message formats type(name) instead of type(value), so the reported type is misleading - it prints the type of the key (str), not the offending value. Treat it as a wrong-type credential entry regardless of what the message says.
Source
Thrown at common/data_source/imap_connector.py:206
```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,
end: SecondsSinceUnixEpoch,
checkpoint: ImapCheckpoint,View on GitHub (pinned to 554fb1133a)
Solutions
- Coerce both values to str when building the credentials dict: str(username), str(password).
- Fix the upstream config so username/password are stored as plain strings, not nested objects or numbers.
- Note the message bug (it prints the type of the key) and inspect the actual dict values when debugging rather than trusting the message.
Example fix
# before
creds = {'username': 1001, 'password': {'value': 'hunter2'}} # -> RuntimeError type mismatch
# after
creds = {'username': '1001', 'password': 'hunter2'} Defensive patterns
Strategy: type-guard
Validate before calling
creds = {'username': str(raw.get('username', '')), 'password': str(raw.get('password', ''))}
if not creds['username'] or not creds['password']:
raise ValueError('IMAP username/password must be non-empty strings') Type guard
def is_flat_str_dict(creds: dict, keys: tuple) -> bool:
return all(type(creds.get(k)) is str for k in keys) Try / catch
try:
connector.load_from_checkpoint(start, end, checkpoint)
except RuntimeError as e:
if 'must be of type str' in str(e):
raise TypeError('IMAP credential values must be plain strings; got a structured value') from e
raise Prevention
- Coerce all credential values to str at the boundary where config is read.
- Avoid nested structures for password fields in config schemas.
- Remember the message prints the key's type, not the value's - inspect the dict directly when debugging.
When it happens
Trigger: The credentials dict contains a numeric username (e.g. 12345) or a nested dict/list as the password for the keys checked in _get_mail_client; any truthy non-string value triggers the branch.
Common situations: Loading credentials from YAML/JSON config where numbers are auto-typed (a numeric mailbox id used as username); wrapping the password in a structure; SDK responses that return nested objects where a flat string was expected.
Related errors
- Credential item {name=} was not found
- Failed to log into imap server; {status=}
- Failed to find any mailboxes for this email account
- Failed to fetch mailboxes; {status=}
- Failed to fetch email ids; {status=}
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/e9cb207410e2b0e4.
Report an issue: GitHub.