microsoft/semantic-kernel · error · FileNotFoundError

Directory {path} not found in repository.

Error message

Directory {path} not found in repository.

What it means

Raised by RepoFilePlugin.list_directory when os.listdir(path) raises FileNotFoundError, i.e. the resolved directory does not exist. The directory path is computed relative to the repo root (four levels up).

Source

Thrown at python/samples/demos/document_generator/plugins/repo_file_plugin.py:51

        path = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..")
        for root, dirs, files in os.walk(path):
            if file_name in files:
                print(f"Found file {file_name} in {root}.")
                with open(os.path.join(root, file_name)) as file:
                    return file.read()
        raise FileNotFoundError(f"File {file_name} not found in repository.")

    @kernel_function(description="List all files or subdirectories in a directory.")
    def list_directory(
        self, path: Annotated[str, "Path of a directory relative to the root of the repository."]
    ) -> Annotated[str, "Returns a list of files and subdirectories as a string."]:
        path = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", path)
        try:
            files = os.listdir(path)
            # Join the list of files into a single string
            return "\n".join(files)
        except FileNotFoundError:
            raise FileNotFoundError(f"Directory {path} not found in repository.")

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Confirm the directory exists relative to the actual repo root.
  2. Verify the plugin's four-level '..' base still points to the repo root after any relocation.
  3. Check the path with os.path.isdir before calling list_directory.
  4. Provide the directory name via read_file_by_name-style search if unsure of the exact path.

Example fix

// before
plugin.list_directory('src')

// after
base = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
target = os.path.join(base, 'python/samples')
plugin.list_directory('python/samples')  # confirmed existing dir
Defensive patterns

Strategy: validation

Validate before calling

import os
base = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
target = os.path.normpath(os.path.join(base, rel_path))
if not os.path.isdir(target):
    raise FileNotFoundError(f'Directory not at {target}')
return os.listdir(target)

Type guard

import os
def is_repo_dir(rel_path: str) -> bool:
    base = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
    target = os.path.normpath(os.path.join(base, rel_path))
    return os.path.isdir(target)

Prevention

When it happens

Trigger: Calling list_directory with a relative path that does not correspond to an existing directory; pointing at a file instead of a directory (raises NotADirectoryError, not caught here); the base resolution is wrong.

Common situations: LLM guesses a directory path; the directory only exists on a different branch; case-sensitivity differences across platforms; the relative base hops are off after the plugin is moved.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/c0b6ad59301d6f94. Report an issue: GitHub.