squidfunk/mkdocs-material · error · PluginError

Couldn't find '{separator}' in post '{path}' in '{docs}'

Error message

Couldn't find '{separator}' in post '{path}' in '{docs}'

What it means

The blog plugin splits post excerpts at a configured separator (default <!-- more -->). When the separator is absent from a post's Markdown and post_excerpt is set to "required", on_page_markdown raises PluginError naming the separator, the post path, and the docs directory. It enforces that every post explicitly marks its excerpt boundary.

Source

Thrown at src/plugins/blog/plugin.py:294

                    raise PluginError(f"Couldn't find author '{id}'")

                # Append to list of authors
                page.authors.append(self.authors[id])

        # Extract settings for excerpts
        separator      = self.config.post_excerpt_separator
        max_authors    = self.config.post_excerpt_max_authors
        max_categories = self.config.post_excerpt_max_categories

        # Ensure presence of separator and throw, if its absent and required -
        # we append the separator to the end of the contents of the post, if it
        # is not already present, so we can remove footnotes or other content
        # from the excerpt without affecting the content of the excerpt
        if separator not in page.markdown:
            if self.config.post_excerpt == "required":
                docs = os.path.relpath(config.docs_dir)
                path = os.path.relpath(page.file.abs_src_path, docs)
                raise PluginError(
                    f"Couldn't find '{separator}' in post '{path}' in '{docs}'"
                )

        # Create excerpt for post and inherit authors and categories - excerpts
        # can contain a subset of the authors and categories of the post
        page.excerpt            = Excerpt(page, config, files)
        page.excerpt.authors    = page.authors[:max_authors]
        page.excerpt.categories = page.categories[:max_categories]

    # Process posts
    def on_page_content(self, html, *, page, config, files):
        if not self.config.enabled:
            return

        # Skip if page is not a post managed by this instance - this plugin has
        # support for multiple instances, which is why this check is necessary
        if page not in self.blog.posts:
            return

View on GitHub (pinned to e2136532f4)

Solutions

  1. Add the separator (default <!-- more -->) into the post where the excerpt should end.
  2. Or relax the config: set post_excerpt: optional (or default) in the blog plugin settings.
  3. If you use a custom separator, ensure posts use exactly that string, including spacing.

Example fix

# before (mkdocs.yml)
plugins:
  - blog:
      post_excerpt: required
# post.md missing separator -> add:
Intro text here...
<!-- more -->

Rest of the post.
Defensive patterns

Strategy: validation

Validate before calling

# CI check: every post contains the excerpt separator
import pathlib
SEP = "<!-- more -->"
for post in pathlib.Path("docs/blog/posts").rglob("*.md"):
    assert SEP in post.read_text(), f"{post} missing '{SEP}'"

Type guard

null

Try / catch

try:
    mkdocs.commands.build.build(config)
except PluginError as e:
    if str(e).startswith("Couldn't find '"):
        print("Insert the excerpt separator in the named post:", e)
    else:
        raise

Prevention

When it happens

Trigger: Configuring post_excerpt: required while a post lacks the <!-- more --> (or custom) separator; writing the separator with wrong casing/spacing; deleting the separator during edits.

Common situations: Customizing post_excerpt_separator in mkdocs.yml but not updating existing posts; authors forgetting to insert <!-- more -->; separators inside code blocks being stripped or altered by other extensions.

Related errors


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