{"record":{"id":"e9cb207410e2b0e4","repo":"infiniflow/ragflow","slug":"credential-item-name-must-be-of-type-str-inste","errorCode":null,"errorMessage":"Credential item {name=} must be of type str, instead received {type(name)=}","messagePattern":"Credential item (.+?) must be of type str, instead received (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"common/data_source/imap_connector.py","lineNumber":206,"sourceCode":"\n        ```py\n        mail_client.login(..)\n        mail_client.logout();\n        mail_client.login(..)\n        ```\n\n        Therefore, you need a fresh, new instance in order to operate with IMAP. This function gives one to you.\n\n        # Notes\n        This function will throw an error if the credentials have not yet been set.\n        \"\"\"\n\n        def get_or_raise(name: str) -> str:\n            value = self.credentials.get(name)\n            if not value:\n                raise RuntimeError(f\"Credential item {name=} was not found\")\n            if not isinstance(value, str):\n                raise RuntimeError(f\"Credential item {name=} must be of type str, instead received {type(name)=}\")\n            return value\n\n        username = get_or_raise(_USERNAME_KEY)\n        password = get_or_raise(_PASSWORD_KEY)\n\n        mail_client = imaplib.IMAP4_SSL(host=self._host, port=self._port)\n        status, _data = mail_client.login(user=username, password=password)\n\n        if status != _IMAP_OKAY_STATUS:\n            raise RuntimeError(f\"Failed to log into imap server; {status=}\")\n\n        return mail_client\n\n    def _load_from_checkpoint(\n        self,\n        start: SecondsSinceUnixEpoch,\n        end: SecondsSinceUnixEpoch,\n        checkpoint: ImapCheckpoint,","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/imap_connector.py#L188-L224","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ncreds = {'username': 1001, 'password': {'value': 'hunter2'}}  # -> RuntimeError type mismatch\n\n# after\ncreds = {'username': '1001', 'password': 'hunter2'}","handlingStrategy":"type-guard","validationCode":"creds = {'username': str(raw.get('username', '')), 'password': str(raw.get('password', ''))}\nif not creds['username'] or not creds['password']:\n    raise ValueError('IMAP username/password must be non-empty strings')","typeGuard":"def is_flat_str_dict(creds: dict, keys: tuple) -> bool:\n    return all(type(creds.get(k)) is str for k in keys)","tryCatchPattern":"try:\n    connector.load_from_checkpoint(start, end, checkpoint)\nexcept RuntimeError as e:\n    if 'must be of type str' in str(e):\n        raise TypeError('IMAP credential values must be plain strings; got a structured value') from e\n    raise","preventionTips":["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."],"tags":["imap","email","credentials","type-error"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}