{"record":{"id":"e9ceca9c72f78b0f","repo":"microsoft/semantic-kernel","slug":"file-path-not-found-in-repository","errorCode":null,"errorMessage":"File {path} not found in repository.","messagePattern":"File (.+?) not found in repository\\.","errorType":"exception","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"python/samples/demos/document_generator/plugins/repo_file_plugin.py","lineNumber":25,"sourceCode":"\n\nclass RepoFilePlugin:\n    \"\"\"A plugin that reads files from this repository.\n\n    This plugin assumes that the code is run within the Semantic Kernel repository.\n    \"\"\"\n\n    @kernel_function(description=\"Read a file given a relative path to the root of the repository.\")\n    def read_file_by_path(\n        self, path: Annotated[str, \"The relative path to the file.\"]\n    ) -> Annotated[str, \"Returns the file content.\"]:\n        path = os.path.join(os.path.dirname(__file__), \"..\", \"..\", \"..\", \"..\", path)\n\n        try:\n            with open(path) as file:\n                return file.read()\n        except FileNotFoundError:\n            raise FileNotFoundError(f\"File {path} not found in repository.\")\n\n    @kernel_function(\n        description=\"Read a file given the name of the file. Function will search for the file in the repository.\"\n    )\n    def read_file_by_name(\n        self, file_name: Annotated[str, \"The name of the file.\"]\n    ) -> Annotated[str, \"Returns the file content.\"]:\n        path = os.path.join(os.path.dirname(__file__), \"..\", \"..\", \"..\", \"..\")\n        for root, dirs, files in os.walk(path):\n            if file_name in files:\n                print(f\"Found file {file_name} in {root}.\")\n                with open(os.path.join(root, file_name)) as file:\n                    return file.read()\n        raise FileNotFoundError(f\"File {file_name} not found in repository.\")\n\n    @kernel_function(description=\"List all files or subdirectories in a directory.\")\n    def list_directory(\n        self, path: Annotated[str, \"Path of a directory relative to the root of the repository.\"]","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/samples/demos/document_generator/plugins/repo_file_plugin.py#L7-L43","documentation":"Raised by RepoFilePlugin.read_file_by_path when open(path) raises FileNotFoundError. The path is resolved relative to the repository root (four levels up from the plugin file). The original FileNotFoundError is caught and re-raised with a descriptive message.","triggerScenarios":"Calling the kernel function with a relative path that does not exist under the repo root; path traversal that escapes the expected tree; the file lives outside the resolved base directory.","commonSituations":"An LLM hallucinates a file path; the plugin's relative base assumption (.. x4) is wrong after the file is moved; case-sensitivity mismatches on case-insensitive dev machines vs Linux.","solutions":["Verify the relative path against the actual repository root layout.","Confirm the plugin file's location so the four '..' hops resolve to the intended base; adjust if the file was relocated.","Use read_file_by_name if you only know the filename and want a tree search.","Normalize/validate the path and check existence with os.path.exists before open()."],"exampleFix":"// before\nplugin.read_file_by_path('src/main.py')\n\n// after\nbase = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))\ntarget = os.path.normpath(os.path.join(base, 'src/main.py'))\nif not os.path.isfile(target):\n    raise FileNotFoundError(f'File not at {target}')\nplugin.read_file_by_path('python/samples/.../src/main.py')","handlingStrategy":"validation","validationCode":"import os\nbase = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))\ntarget = os.path.normpath(os.path.join(base, rel_path))\nif not os.path.isfile(target):\n    raise FileNotFoundError(f'File not at {target}')\nwith open(target) as f:\n    return f.read()","typeGuard":"import os\ndef is_valid_repo_path(rel_path: str) -> bool:\n    base = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))\n    target = os.path.normpath(os.path.join(base, rel_path))\n    return os.path.isfile(target) and target.startswith(base)","tryCatchPattern":"try:\n    return plugin.read_file_by_path(rel_path)\nexcept FileNotFoundError as ex:\n    # fall back to name-based search or inform the model\n    raise","preventionTips":["Pin the plugin file location or compute the base dynamically.","Reject path traversal (target.startswith(base)).","Prefer read_file_by_name when only the filename is known."],"tags":["filesystem","kernel-plugin","file-not-found","path-resolution"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}