squidfunk/mkdocs-material · error · PluginError

Couldn't parse due to possible syntax error in HTML

Error message

Couldn't parse due to possible syntax error in HTML: 

{fragment}

What it means

The privacy plugin extracts external asset URLs from page HTML using regex-based parsing. When the tag fragment it extracted cannot be parsed — typically because the author wrote invalid HTML such as an unclosed or unquoted attribute — the plugin aborts with PluginError showing the offending fragment, since regex extraction cannot reliably proceed on malformed markup.

Solutions

  1. Inspect the printed fragment and fix the HTML syntax error (missing quote, missing '>' or closing tag) in the source Markdown/HTML
  2. Validate the page HTML (e.g. run a linter or paste into an HTML validator) to find the malformed tag
  3. If generated by a macro/template, fix the generator to emit well-formed attributes

Example fix

<!-- before -->
<img src="https://example.com/logo.png alt="logo">
<!-- after -->
<img src="https://example.com/logo.png" alt="logo">
Defensive patterns

Strategy: validation

Validate before calling

from html.parser import HTMLParser
class _V(HTMLParser):
    def error(self, m): raise ValueError(m)
_V().feed(fragment)  # raises on obviously malformed markup before build

Try / catch

try:
    mkdocs build
except SystemExit:
    # message prints the failing fragment; fix the quoted HTML
    pass

Prevention

When it happens

Trigger: on_page_content (or replace) encounters an external-asset tag in the page whose extracted HTML fragment fails the plugin's parser, e.g. <img src="https://... > with a missing closing quote, or a missing closing tag, so the regex extraction yields an unparseable fragment.

Common situations: Hand-edited HTML with a forgotten closing quote or tag; templating/macros generating attributes with unescaped quotes; minifiers or shortcodes emitting non-well-formed tags that confuse the regex-based extractor.

Related errors


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

Appendix: source

Thrown at src/plugins/privacy/plugin.py:317

        return False

    # -------------------------------------------------------------------------

    # Parse a fragment
    def _parse_fragment(self, fragment: str):
        parser = FragmentParser()
        parser.feed(fragment)
        parser.close()

        # Check parse result and return element
        if isinstance(parser.result, Element):
            return parser.result

        # Otherwise, raise a plugin error - if the author accidentally used
        # invalid HTML inside of the tag, e.g., forget a opening or closing
        # quote, we need to catch this here, as we're using pretty basic
        # regular expression based extraction
        raise PluginError(
            "Couldn't parse due to possible syntax error in HTML: \n\n"
            + fragment
        )

    # Parse and extract all external assets from a media file using a preset
    # regular expression, and return all URLs found.
    def _parse_media(self, initiator: File) -> list[URL]:
        _, extension = posixpath.splitext(initiator.dest_uri)
        if extension not in self.assets_expr_map:
            return []

        # Skip if source path is not set, which might be true for generated
        # files or for files that were added programatically in plugins
        if not initiator.abs_src_path:
            return []

        # Find and extract all external asset URLs
        expr = re.compile(self.assets_expr_map[extension], flags = re.I | re.M)

View on GitHub (pinned to e2136532f4)