squidfunk/mkdocs-material · error · ValidationError

Expected string, but received

Error message

Expected string, but received: {url}

What it means

After confirming the mapping item is a dictionary, _mapping_item_from_json requires its 'url' field to be a string so it can construct an mkdocs Link. This ValidationError is thrown when 'url' is missing (None) or of another JSON type (number, object, array, bool).

Solutions

  1. Add or fix the 'url' field inside each mapping's item so it is a plain string URL path, e.g. "url": "guide/setup/"
  2. Regenerate the mapping file by rebuilding the source project with MappingStorage.save()
  3. Search the JSON for items missing "url" (e.g. with jq: .mappings[] | select(.item.url | type != "string"))
  4. If a script writes the file, make it serialize item.url as str(item.url)

Example fix

// before
{"item": {"title": "Setup"}, "tags": ["setup"]}
// after
{"item": {"url": "setup/", "title": "Setup"}, "tags": ["setup"]}
Defensive patterns

Strategy: validation

Validate before calling

import json
with open(path) as f:
    data = json.load(f)
for m in data.get("mappings", []):
    url = (m.get("item") or {}).get("url")
    if not isinstance(url, str):
        raise ValueError(f"entry {m!r}: item.url must be a string")

Type guard

def item_has_url(entry: dict) -> bool:
    item = entry.get("item")
    return isinstance(item, dict) and isinstance(item.get("url"), str)

Try / catch

from mkdocs.config.base import ValidationError
try:
    mappings = list(storage.load(path))
except ValidationError as err:
    log.error("Item missing/invalid url in %s: %s", path, err)
    mappings = []

Prevention

When it happens

Trigger: MappingStorage.load(path) reads a mapping entry where data['item']['url'] is absent, null, or e.g. a nested object/array instead of a string like "guide/setup/".

Common situations: Hand-edited mapping files where the url key was renamed or deleted; a custom exporter that emitted url as a list of path segments; partially written JSON from a crashed build.

Related errors


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

Appendix: source

Thrown at src/plugins/tags/structure/mapping/storage/__init__.py:199

    When loading a mapping, we must always return a link, as the sources of
    pages might not be available because we're building another project.

    Arguments:
        data: Serialized representation.

    Returns:
        The link.
    """
    if not isinstance(data, dict):
        raise ValidationError(
            f"Expected dictionary, but received: {data}"
        )

    # Ensure item has URL
    url = data.get("url")
    if not isinstance(url, str):
        raise ValidationError(
            f"Expected string, but received: {url}"
        )

    # Ensure item has title
    title = data.get("title")
    if not isinstance(title, str):
        raise ValidationError(
            f"Expected string, but received: {title}"
        )

    # Create and return item
    return Link(title, url)

View on GitHub (pinned to e2136532f4)