{"record":{"id":"82f328b2b7eadf0d","repo":"squidfunk/mkdocs-material","slug":"error-reading-categories-of-post-path-in-doc","errorCode":null,"errorMessage":"Error reading categories of post '{path}' in '{docs}': category '{name}' not in allow list","messagePattern":"Error reading categories of post '(.+?)' in '(.+?)': category '(.+?)' not in allow list","errorType":"exception","errorClass":"PluginError","httpStatus":null,"severity":"error","filePath":"src/plugins/blog/plugin.py","lineNumber":588,"sourceCode":"                yield Archive(name, file, config)\n\n            # Assign post to archive\n            assert isinstance(file.page, Archive)\n            file.page.posts.append(post)\n\n    # Generate views for categories - analyze posts and generate the necessary\n    # views, taking the allowed categories as set by the author into account\n    def _generate_categories(self, config: MkDocsConfig, files: Files):\n        for post in self.blog.posts:\n            for name in post.config.categories:\n                path = self._format_path_for_category(name)\n\n                # Ensure category is in non-empty allow list\n                categories = self.config.categories_allowed or [name]\n                if name not in categories:\n                    docs = os.path.relpath(config.docs_dir)\n                    path = os.path.relpath(post.file.abs_src_path, docs)\n                    raise PluginError(\n                        f\"Error reading categories of post '{path}' in \"\n                        f\"'{docs}': category '{name}' not in allow list\"\n                    )\n\n                # Create file for view, if it does not exist\n                file = files.get_file_from_path(path)\n                if not file:\n                    file = self._path_to_file(path, config)\n                    files.append(file)\n\n                    # Create file in temporary directory\n                    self._save_to_file(file.abs_src_path, f\"# {name}\")\n\n                # Temporarily remove view from navigation\n                file.inclusion = InclusionLevel.EXCLUDED\n\n                # Create and yield view\n                if not isinstance(file.page, Category):","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/squidfunk/mkdocs-material/blob/e2136532f40aed98af1f6497c0cc6a3cff9f759b/src/plugins/blog/plugin.py#L570-L606","documentation":"The mkdocs-material blog plugin only creates category view pages for categories listed in the plugin's `categories_allowed` configuration option. When a post's YAML metadata declares a category that is not in that allow list, `_generate_categories` (invoked from the `on_files` event) aborts the build with this PluginError. The allow list must be non-empty; if it is empty the plugin falls back to treating the post's own category name as allowed.","triggerScenarios":"A post defines `categories: [something]` in its metadata while `plugins.blog.categories_allowed` in mkdocs.yml lists other names (or a typo'd name), and the blog plugin tries to generate the category view page for it.","commonSituations":"Adding a new category to posts without updating `categories_allowed`; typos or case mismatches between post metadata and mkdocs.yml; copying posts from another project with different allowed categories.","solutions":["Add the missing category name to `categories_allowed` under the blog plugin settings in mkdocs.yml","Fix the typo/case mismatch in the post's `categories` metadata so it matches the allow list","Remove the `categories` key from the post if it should not be categorized"],"exampleFix":"# before (mkdocs.yml)\nplugins:\n  - blog:\n      categories_allowed: [Tutorials]\n# post has: categories: [News]\n\n// after\nplugins:\n  - blog:\n      categories_allowed: [Tutorials, News]","handlingStrategy":"validation","validationCode":"import yaml, pathlib\nallowed = set(cfg['plugins']['blog']['categories_allowed'])\nfor post in pathlib.Path('docs/posts').rglob('*.md'):\n    meta = next(yaml.safe_load_all(post.read_text().split('---')[1:2])[0] for _ in [0]) if post.read_text().startswith('---') else {}\n    for cat in (meta.get('categories') or []):\n        assert cat in allowed, f\"{post}: category '{cat}' not allowed\"\n","typeGuard":"def is_allowed(name, allowed):\n    return bool(allowed) and name in allowed\n","tryCatchPattern":"try:\n    mkdocs.commands.build(config)\nexcept PluginError as e:\n    if \"not in allow list\" in str(e):\n        log.error(f\"Fix categories_allowed or the post metadata: {e}\")\n    raise\n","preventionTips":["Keep `categories_allowed` in sync whenever you add a new category to any post","Centralize category names in a shared list or lint script that checks posts against mkdocs.yml","Watch for case/typo differences between post metadata and mkdocs.yml"],"tags":["mkdocs","blog-plugin","config-validation","category"],"backgroundTag":"value-not-in-allowed-list","analyzedSha":"e2136532f40aed98af1f6497c0cc6a3cff9f759b","analyzedAt":"2026-08-29T11:20:04.299Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}