squidfunk/mkdocs-material · error · ValidationError

Expected iterable tags, but received: {value}

Error message

Expected iterable tags, but received: {value}

What it means

TagSet.run_validation validates tag values coming from page front matter (the 'tags' key) or from plugin filters like tags listings. The value must be an iterable collection of tags — but explicitly NOT a plain string, since a string would iterate character-by-character. This mkdocs ValidationError is raised when the value is neither None nor a non-string iterable (e.g. a number, a bool, or a single string).

Source

Thrown at src/plugins/tags/structure/tag/options.py:82

        Validate list of tags.

        If the value is `None`, an empty set is returned. Otherwise, the value
        is expected to be a list of tags, which is converted to a set of tags.
        This means that tags are automatically deduplicated. Note that tags are
        not expanded here, as the set is intended to be checked exactly.

        Arguments:
            value: The value to validate.

        Returns:
            A set of tags.
        """
        if value is None:
            return set()

        # Ensure tags are iterable
        if not isinstance(value, Iterable) or isinstance(value, str):
            raise ValidationError(
                f"Expected iterable tags, but received: {value}"
            )

        # Ensure tags are valid
        tags: set[Tag] = set()
        for index, tag in enumerate(value):
            if not isinstance(tag, (str, int, float, bool)):
                raise ValidationError(
                    f"Expected a {str}, {int}, {float} or {bool} "
                    f"but received: {type(tag)} at index {index}"
                )

            # Coerce tag to string and add to set
            tags.add(Tag(str(tag)))

        # Ensure tags are in allow list, if any
        if self.allowed:
            invalid = tags.difference(self.allowed)

View on GitHub (pinned to e2136532f4)

Solutions

  1. Wrap the value in a list in front matter: tags: [my-tag] or tags:\n - my-tag
  2. Check YAML indentation — an incorrectly indented block can parse as a scalar string instead of a list
  3. If the page has no tags, omit the key or use tags: [] (null is allowed and yields an empty set)
  4. Validate front matter with mkdocs serve/build and inspect the offending page named in the error context

Example fix

# before (front matter)
---
tags: my-tag
---
# after
---
tags:
  - my-tag
---
Defensive patterns

Strategy: validation

Validate before calling

import yaml
def validate_tags(fm: dict) -> None:
    tags = fm.get("tags")
    if tags is None:
        return
    if isinstance(tags, str) or not hasattr(tags, "__iter__"):
        raise ValueError(f"tags must be a list, got: {tags!r}")
validate_tags(yaml.safe_load(front_matter))

Type guard

def is_tag_list(value: object) -> bool:
    return value is None or (
        isinstance(value, (list, tuple, set))
        and not isinstance(value, str)
    )

Try / catch

from mkdocs.config.base import ValidationError
try:
    page_tags = tag_option.run_validation(raw_value)
except ValidationError as err:
    log.error("Bad 'tags' front matter on page: %s", err)

Prevention

When it happens

Trigger: A page's front matter sets tags: my-tag (a bare string instead of a list); tags: true or tags: 3; or a TagSet filter option receives a scalar instead of a list of tags.

Common situations: YAML front matter typo where the author forgot the list syntax and wrote tags: foo instead of tags: [foo] or tags:\n - foo; copying a single-tag example from docs; a template or script injecting a scalar into front matter.

Related errors


AI-assisted analysis of squidfunk/mkdocs-material@e2136532f4 (2026-08-29). Data as JSON: /api/errors/60503633fb65abed. Report an issue: GitHub.