deepset-ai/haystack · error

Unknown link format '{link_format}'. Supported formats are:

Error message

Unknown link format '{link_format}'. Supported formats are: 'markdown', 'plain', 'none'

What it means

XLSXToDocument's __init__ validates link_format: it must be one of 'markdown', 'plain', or 'none'. Unlike LinkFormat.from_str, this check is a literal tuple membership test and is case-sensitive. Invalid values raise ValueError during component construction.

Source

Thrown at haystack/components/converters/xlsx.py:86

            - If `table_format` is "csv", these arguments are passed to `pandas.DataFrame.to_csv`.
              See https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html#pandas-dataframe-to-csv
            - If `table_format` is "markdown", these arguments are passed to `pandas.DataFrame.to_markdown`.
              See https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_markdown.html#pandas-dataframe-to-markdown
        :param link_format: The format for link output. Possible options:
            - `"markdown"`: `[text](url)`
            - `"plain"`: `text (url)`
            - `"none"`: Only the text is extracted, link addresses are ignored.
        :param store_full_path:
            If True, the full path of the file is stored in the metadata of the document.
            If False, only the file name is stored.
        """
        pandas_xlsx_import.check()
        self.table_format = table_format
        if table_format not in ["csv", "markdown"]:
            raise ValueError(f"Unsupported export format: {table_format}. Choose either 'csv' or 'markdown'.")
        if link_format not in ("markdown", "plain", "none"):
            msg = f"Unknown link format '{link_format}'. Supported formats are: 'markdown', 'plain', 'none'"
            raise ValueError(msg)
        if table_format == "markdown":
            tabulate_import.check()
        self.link_format = link_format
        self.sheet_name = sheet_name
        self.read_excel_kwargs = read_excel_kwargs or {}
        self.table_format_kwargs = table_format_kwargs or {}
        self.store_full_path = store_full_path

    @component.output_types(documents=list[Document])
    def run(
        self, sources: list[str | Path | ByteStream], meta: dict[str, Any] | list[dict[str, Any]] | None = None
    ) -> dict[str, list[Document]]:
        """
        Converts a XLSX file to a Document.

        :param sources:
            List of file paths or ByteStream objects.
        :param meta:

View on GitHub (pinned to e318778c9b)

Solutions

  1. Pass exactly 'markdown', 'plain', or 'none' (lowercase strings).
  2. If you have a LinkFormat enum, pass .value (e.g. LinkFormat.MARKDOWN.value) — but only if it equals one of the three accepted strings.
  3. Match casing exactly; the membership test is case-sensitive.

Example fix

# before
from haystack.components.converters.utils import LinkFormat
converter = XLSXToDocument(link_format=LinkFormat.MARKDOWN)  # enum, not str
# after
converter = XLSXToDocument(link_format="markdown")
Defensive patterns

Strategy: validation

Validate before calling

VALID_LINK_FORMATS = ("markdown", "plain", "none")

assert link_format in VALID_LINK_FORMATS, (
    f"link_format={link_format!r} invalid; use one of {VALID_LINK_FORMATS}"
)

Type guard

from typing import Literal
LinkFmt = Literal["markdown", "plain", "none"]

def is_link_fmt(v: object) -> bool:
    return isinstance(v, str) and v in ("markdown", "plain", "none")

Try / catch

try:
    converter = XLSXToDocument(link_format=link_format)
except ValueError as e:
    logger.warning("Invalid link_format, defaulting to 'markdown': %s", e)
    converter = XLSXToDocument(link_format="markdown")

Prevention

When it happens

Trigger: Instantiating XLSXToDocument(link_format=...) with e.g. 'md', 'text', 'href', 'Markdown', or a LinkFormat enum object (an enum instance is not equal to the plain strings in the tuple).

Common situations: Typo or wrong casing in pipeline YAML; passing a PyPDF/XLSX LinkFormat enum member where a raw string is expected; copying link_format values from other converters that use different vocabularies.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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