infiniflow/ragflow · error · RuntimeError

Failed to fetch mailboxes; {status=}

Error message

Failed to fetch mailboxes; {status=}

What it means

Raised by _fetch_all_mailboxes_for_email_account when mail_client.list returns a status other than 'OK'. Unlike the empty-result case, the server explicitly reported failure for the LIST command. This usually indicates a session-level problem (dropped connection, unselected state, server-side refusal) rather than missing folders.

Source

Thrown at common/data_source/imap_connector.py:386

                if not (start_dt < msg_dt <= end_dt):
                    continue

                slim_doc_batch.append(SlimDocument(id=email_headers.id))
                for att in extract_attachments(email_msg):
                    slim_doc_batch.append(SlimDocument(id=_attachment_document_id(email_headers.id, att)))

                if len(slim_doc_batch) >= _PAGE_SIZE:
                    yield slim_doc_batch
                    slim_doc_batch = []

        if slim_doc_batch:
            yield slim_doc_batch


def _fetch_all_mailboxes_for_email_account(mail_client: imaplib.IMAP4_SSL) -> list[str]:
    status, mailboxes_data = mail_client.list('""', "*")
    if status != _IMAP_OKAY_STATUS:
        raise RuntimeError(f"Failed to fetch mailboxes; {status=}")

    mailboxes = []

    for mailboxes_raw in mailboxes_data:
        if isinstance(mailboxes_raw, bytes):
            mailboxes_str = mailboxes_raw.decode()
        elif isinstance(mailboxes_raw, str):
            mailboxes_str = mailboxes_raw
        else:
            logging.warning(f"Expected the mailbox data to be of type str, instead got {type(mailboxes_raw)=} {mailboxes_raw}; skipping")
            continue

        # The mailbox LIST response output can be found here:
        # https://www.rfc-editor.org/rfc/rfc3501.html#section-7.2.2
        #
        # The general format is:
        # `(<name-attributes>) <hierarchy-delimiter> <mailbox-name>`
        #

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Retry the operation - build a fresh mail client via _get_mail_client() and re-run the checkpoint load.
  2. If persistent, reproduce with a manual LIST (e.g. via Python imaplib) to see the server's exact response and status text.
  3. Check server logs / ACLs if LIST is being denied for this authenticated user.
  4. For long jobs, reduce idle time between login and first command or implement reconnect logic upstream.

Example fix

# before
mailboxes = _fetch_all_mailboxes_for_email_account(client)  # RuntimeError: status='NO'

# after
for attempt in range(3):
    try:
        mailboxes = _fetch_all_mailboxes_for_email_account(client)
        break
    except RuntimeError:
        client = connector._get_mail_client()  # fresh session
else:
    raise
Defensive patterns

Strategy: retry

Try / catch

for attempt in range(3):
    try:
        mailboxes = _fetch_all_mailboxes_for_email_account(client)
        break
    except RuntimeError as e:
        if 'Failed to fetch mailboxes' not in str(e) or attempt == 2:
            raise
        time.sleep(2 ** attempt)
        client = connector._get_mail_client()  # fresh authenticated session

Prevention

When it happens

Trigger: The IMAP session timed out or was closed between login and LIST; the server rejects LIST with 'NO' due to ACL or namespace restrictions; a transient server failure mid-sync. Raised as a RuntimeError with the raw status string embedded.

Common situations: Long-running sync jobs where the connection idles out; load-shedding or maintenance windows on the mail server; aggressive per-command rate limiting; proxies or middleboxes between client and server.

Related errors


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