{"record":{"id":"dcbe3ce7ed627024","repo":"tiangolo/fastapi","slug":"path-must-be-inside-en-docs-path","errorCode":null,"errorMessage":"Path must be inside {en_docs_path}","messagePattern":"Path must be inside (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"scripts/docs.py","lineNumber":843,"sourceCode":"        remaining = [\n            f\n            for f in dir_path.iterdir()\n            if f.name != \"__pycache__\" and f.name != \"__init__.py\"\n        ]\n        if not remaining:\n            logging.info(f\"Removing empty/init-only directory: {dir_path}\")\n            shutil.rmtree(dir_path)\n    print(f\"Removed {removed} unused file(s) ✅\")\n\n\n@app.command()\ndef add_permalinks_page(path: Path, update_existing: bool = False):\n    \"\"\"\n    Add or update header permalinks in specific page of En docs.\n    \"\"\"\n\n    if not path.is_relative_to(en_docs_path / \"docs\"):\n        raise RuntimeError(f\"Path must be inside {en_docs_path}\")\n    rel_path = path.relative_to(en_docs_path / \"docs\")\n\n    # Skip excluded sections\n    if str(rel_path).startswith(non_translated_sections):\n        return\n\n    visible_text_extractor = VisibleTextExtractor()\n    updated_lines = []\n    in_code_block3 = False\n    in_code_block4 = False\n    permalinks = set()\n\n    with path.open(\"r\", encoding=\"utf-8\") as f:\n        lines = f.readlines()\n\n    for line in lines:\n        # Handle codeblocks start and end\n        if not (in_code_block3 or in_code_block4):","sourceCodeStart":825,"sourceCodeEnd":861,"githubUrl":"https://github.com/tiangolo/fastapi/blob/3e8d1526d83a90aaf7d6eb6dc682bf150f180b25/scripts/docs.py#L825-L861","documentation":"Raised by add_permalinks_page() in scripts/docs.py:843. The permalink tool only operates on English docs, so it guards with path.is_relative_to(en_docs_path / 'docs') (scripts/docs.py:842). Any path outside docs/en/docs/ is rejected to avoid writing permalinks into translated content or unrelated files.","triggerScenarios":"Invoking the `add-permalinks-page` Typer command (or add_permalinks_page directly) with a Path that does not resolve under docs/en/docs/. Also reachable via add_permalinks / add_permalinks_pages which iterate paths and call this function.","commonSituations":"Passing a translated docs path (e.g. docs/es/docs/...) by mistake. Passing a relative path resolved from the wrong working directory. Passing a docs_src path or a path under the repo root.","solutions":["Pass a path under docs/en/docs/, e.g. docs/en/docs/index.md.","If calling from another working directory, resolve the path against the repo root first.","For translated docs, run the translation tooling instead — permalinks are propagated via replace_header_permalinks in doc_parsing_utils.py."],"exampleFix":"# before\npython scripts/docs.py add-permalinks-page docs/es/docs/index.md\n# after\npython scripts/docs.py add-permalinks-page docs/en/docs/index.md","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef is_en_doc(p: Path) -> bool:\n    return p.is_relative_to(Path(\"docs/en/docs\"))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass a path resolved under docs/en/docs/ to add-permalinks-page.","Resolve relative paths against the repo root before passing them in.","Use add_permalinks (no args) to process every English doc safely."],"tags":["docs","validation","paths","permalinks"],"backgroundTag":null,"analyzedSha":"3e8d1526d83a90aaf7d6eb6dc682bf150f180b25","analyzedAt":"2026-08-11T02:34:52.986Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}