squidfunk/mkdocs-material · error · ValidationError
Expected list, but received: {tags}
Error message
Expected list, but received: {tags} What it means
Within a deserialized mapping, `_mapping_from_json` requires the `tags` field to be a list and then each tag to be a string; a non-list `tags` value (or, per the following loop, non-string elements) raises this ValidationError, ensuring tag data is uniformly typed.
Source
Thrown at src/plugins/tags/structure/mapping/storage/__init__.py:161
def _mapping_from_json(data: object) -> Mapping:
"""
Return a mapping from a serialized representation.
Arguments:
data: Serialized representation.
Returns:
The mapping.
"""
if not isinstance(data, dict):
raise ValidationError(
f"Expected dictionary, but received: {data}"
)
# Ensure tags are iterable
tags = data.get("tags")
if not isinstance(tags, list):
raise ValidationError(
f"Expected list, but received: {tags}"
)
# Ensure tags are valid
for tag in tags:
if not isinstance(tag, str):
raise ValidationError(
f"Expected string, but received: {tag}"
)
# Create and return mapping
return Mapping(
_mapping_item_from_json(data.get("item")),
tags = [Tag(tag) for tag in tags]
)
def _mapping_item_from_json(data: object) -> Link:
"""View on GitHub (pinned to e2136532f4)
Solutions
- Change `tags` to an array of strings: `{"tags": ["tag-a"]}`.
- Convert any single tag string into a one-element list.
- Regenerate the mappings file with the plugin's export tooling to get canonical shapes.
- Validate with a guard (`isinstance(tags, list) and all(isinstance(t, str) for t in tags)`) before loading.
Example fix
// before
{"tags": "tag-a"}
// after
{"tags": ["tag-a"]} Defensive patterns
Strategy: type-guard
Validate before calling
import json
data = json.load(open(path))
for i, entry in enumerate(data.get('mappings', [])):
tags = entry.get('tags')
assert isinstance(tags, list) and all(isinstance(t, str) for t in tags), f"mappings[{i}].tags must be a list of strings" Type guard
def has_valid_tags(entry):
tags = entry.get('tags') if isinstance(entry, dict) else None
return isinstance(tags, list) and all(isinstance(t, str) for t in tags) Try / catch
try:
yield from storage.load(path)
except ValidationError as e:
log.error(f"Invalid tags field in {path}: {e}")
raise SystemExit(1) Prevention
- Always serialize tags as an array of strings, even for a single tag
- Add a pre-export assertion that every tags value is a list[str]
- Regenerate files with current tooling after version upgrades
When it happens
Trigger: A mapping entry where `tags` is a string (`"tag-a"`), an object, or null instead of an array of strings; entries with numeric or nested-structure tag elements.
Common situations: Hand-authored exports using a single tag string; JSON produced by scripts that forgot to wrap a tag in a list; front matter styles where tags were a scalar and exported as-is.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Expected dictionary, but received: {data}
- Expected list, but received: {mappings}
- Error reading tags of page '{path}' in '{docs}': {e}
- Couldn't find listing configuration: {data}. Available confi
- Error reading listing configuration in '{path}': {e}
AI-assisted analysis of squidfunk/mkdocs-material@e2136532f4 (2026-08-29).
Data as JSON: /api/errors/f4fbd897a6fc895d.
Report an issue: GitHub.