docling-project/docling · error · TypeError

Unsupported input type: {type(self.path_or_stream)}

Error message

Unsupported input type: {type(self.path_or_stream)}

What it means

EmailDocumentBackend._read_bytes() only accepts BytesIO or Path inputs and raises TypeError for anything else (str paths, file objects opened in text mode, TemporaryFile wrappers, etc.). Because the call sits inside the init try-block, callers normally see it wrapped in the email backend's DocumentLoadError, with the TypeError as __cause__.

Source

Thrown at docling/backend/email_backend.py:111

            self.is_msg = raw.startswith(_MSG_MAGIC)
            if self.is_msg:
                raw = self._msg_to_rfc822_bytes(raw)
            self.mail = mailparser.parse_from_bytes(raw)

            self.valid = self.mail is not None
        except ImportError:
            raise
        except Exception as exc:
            raise DocumentLoadError(
                f"Could not initialize email backend for file with hash {self.document_hash}."
            ) from exc

    def _read_bytes(self) -> bytes:
        if isinstance(self.path_or_stream, BytesIO):
            return self.path_or_stream.getvalue()
        if isinstance(self.path_or_stream, Path):
            return self.path_or_stream.read_bytes()
        raise TypeError(f"Unsupported input type: {type(self.path_or_stream)}")

    @staticmethod
    def _header_safe(value: str) -> str:
        # Email header values must be single-line; collapse CR/LF to spaces so a
        # crafted .msg cannot inject headers and EmailMessage does not reject it.
        return value.replace("\r", " ").replace("\n", " ").strip()

    @staticmethod
    def _msg_to_rfc822_bytes(data: bytes) -> bytes:
        """Project an Outlook ``.msg`` (OLE2/CFB) onto RFC 822 bytes.

        python-oxmsg reads the MAPI message; we assemble a standard
        ``email.message.EmailMessage`` from it so the ``.msg`` path shares the
        exact body, HTML, address, and attachment handling used for ``.eml``
        input.
        """
        if not _OXMSG_AVAILABLE:
            raise ImportError(_MSG_INSTALL_HINT) from _OXMSG_IMPORT_ERROR

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Convert str paths to pathlib.Path before calling the API
  2. Wrap other binary file objects: BytesIO(open(p,'rb').read())
  3. Never pass StringIO or text-mode handles; the backend needs bytes

Example fix

# before
backend = EmailDocumentBackend(in_doc, '/data/mail.eml')  # str not accepted

# after
from pathlib import Path
backend = EmailDocumentBackend(in_doc, Path('/data/mail.eml'))
# or for streams: EmailDocumentBackend(in_doc, BytesIO(raw_bytes))
Defensive patterns

Strategy: type-guard

Validate before calling

from io import BytesIO
from pathlib import Path

def normalize(src):
    if isinstance(src, str):
        return Path(src)
    if isinstance(src, Path):
        return src
    if isinstance(src, BytesIO):
        return src
    if hasattr(src, 'read'):
        return BytesIO(src.read())
    raise TypeError(f'unsupported source: {type(src)!r}')

Type guard

def is_accepted_source(src) -> bool:
    return isinstance(src, (BytesIO, Path))

Prevention

When it happens

Trigger: Passing a string path instead of pathlib.Path, an open() file object, an io.FileIO, or any stream type other than BytesIO (e.g. io.StringIO) as path_or_stream to the email backend.

Common situations: Wrapping Docling in a service that forwards urllib/tempfile handles; legacy code using os.path strings; tests using StringIO for text fixtures.

Related errors


AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14). Data as JSON: /api/errors/949b074eac68e044. Report an issue: GitHub.