deepset-ai/haystack · error

Unsupported source type {type(source)}

Error message

Unsupported source type {type(source)}

What it means

get_bytestream_from_source normalizes converter sources into a ByteStream. It accepts an existing ByteStream, or a str/Path file path; anything else raises ValueError. This validates the `sources` input of HTMLToDocument-family converters before file loading.

Source

Thrown at haystack/components/converters/utils.py:56

def get_bytestream_from_source(source: str | Path | ByteStream, guess_mime_type: bool = False) -> ByteStream:
    """
    Creates a ByteStream object from a source.

    :param source:
        A source to convert to a ByteStream. Can be a string (path to a file), a Path object, or a ByteStream.
    :param guess_mime_type:
        Whether to guess the mime type from the file.
    :return:
        A ByteStream object.
    """

    if isinstance(source, ByteStream):
        return source
    if isinstance(source, (str, Path)):
        bs = ByteStream.from_file_path(Path(source), guess_mime_type=guess_mime_type)
        bs.meta["file_path"] = str(source)
        return bs
    raise ValueError(f"Unsupported source type {type(source)}")


def normalize_metadata(meta: dict[str, Any] | list[dict[str, Any]] | None, sources_count: int) -> list[dict[str, Any]]:
    """
    Normalize the metadata input for a converter.

    Given all the possible value of the meta input for a converter (None, dictionary or list of dicts),
    makes sure to return a list of dictionaries of the correct length for the converter to use.

    :param meta: the meta input of the converter, as-is
    :param sources_count: the number of sources the converter received
    :returns: a list of dictionaries of the make length as the sources list

    Each source always gets its own independent dictionary. When ``meta`` is ``None`` or a single
    dictionary, a separate copy is returned for every source so that mutating one source's metadata
    downstream does not leak into the others.
    """
    if meta is None:

View on GitHub (pinned to e318778c9b)

Solutions

  1. Convert the input first: use ByteStream.from_file_path(Path(source)) for local files or ByteStream(data=...) for in-memory bytes.
  2. For URLs, download with a fetcher component (e.g. LinkContentFetcher) before the converter.
  3. Ensure upstream components emit file paths or ByteStreams, not Documents or file handles.

Example fix

# before
converter.run(sources=["https://example.com/page.html"])  # ValueError
# after
from haystack.dataclasses import ByteStream
import requests
data = requests.get("https://example.com/page.html").content
converter.run(sources=[ByteStream(data=data, meta={"url": "https://example.com/page.html"})])
Defensive patterns

Strategy: type-guard

Validate before calling

from pathlib import Path
from haystack.dataclasses import ByteStream

def is_valid_source(s) -> bool:
    return isinstance(s, (ByteStream, str, Path))

bad = [s for s in sources if not is_valid_source(s)]
if bad:
    raise TypeError(f"Convert ByteStream/str/Path required, got: {[type(s) for s in bad]}")

Type guard

from pathlib import Path
from haystack.dataclasses import ByteStream

def as_source(s: object) -> ByteStream:
    if isinstance(s, ByteStream):
        return s
    if isinstance(s, (str, Path)):
        bs = ByteStream.from_file_path(Path(s))
        bs.meta["file_path"] = str(s)
        return bs
    raise TypeError(f"Unsupported source type {type(s)}")

Try / catch

try:
    result = converter.run(sources=sources)
except ValueError as e:
    if "Unsupported source type" in str(e):
        sources = [as_source(s) for s in sources]
        result = converter.run(sources=sources)
    else:
        raise

Prevention

When it happens

Trigger: Calling get_bytestream_from_source (or a converter's run(sources=...)) with an unsupported object such as a URL string, an open file handle, bytes, or a Document, rather than a ByteStream, str path, or Path.

Common situations: Passing a URL expecting the converter to download it; passing a file-like object from open(); passing raw bytes; upstream pipeline component emitting Documents instead of paths/ByteStreams.

Related errors


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/5488981f47cff930. Report an issue: GitHub.