{"record":{"id":"1c22919c07efc8c7","repo":"FoundationAgents/MetaGPT","slug":"invalid-root","errorCode":null,"errorMessage":"Invalid root","messagePattern":"Invalid root","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"metagpt/utils/project_repo.py","lineNumber":99,"sourceCode":"        self.data_api_design = git_repo.new_file_repository(relative_path=DATA_API_DESIGN_FILE_REPO)\n        self.seq_flow = git_repo.new_file_repository(relative_path=SEQ_FLOW_FILE_REPO)\n        self.system_design = git_repo.new_file_repository(relative_path=SYSTEM_DESIGN_PDF_FILE_REPO)\n        self.prd = git_repo.new_file_repository(relative_path=PRD_PDF_FILE_REPO)\n        self.api_spec_and_task = git_repo.new_file_repository(relative_path=TASK_PDF_FILE_REPO)\n        self.code_summary = git_repo.new_file_repository(relative_path=CODE_SUMMARIES_PDF_FILE_REPO)\n        self.sd_output = git_repo.new_file_repository(relative_path=SD_OUTPUT_FILE_REPO)\n        self.code_plan_and_change = git_repo.new_file_repository(relative_path=CODE_PLAN_AND_CHANGE_PDF_FILE_REPO)\n        self.graph_repo = git_repo.new_file_repository(relative_path=VISUAL_GRAPH_REPO_FILE_REPO)\n\n\nclass ProjectRepo(FileRepository):\n    def __init__(self, root: str | Path | GitRepository):\n        if isinstance(root, str) or isinstance(root, Path):\n            git_repo_ = GitRepository(local_path=Path(root))\n        elif isinstance(root, GitRepository):\n            git_repo_ = root\n        else:\n            raise ValueError(\"Invalid root\")\n        super().__init__(git_repo=git_repo_, relative_path=Path(\".\"))\n        self._git_repo = git_repo_\n        self.docs = DocFileRepositories(self._git_repo)\n        self.resources = ResourceFileRepositories(self._git_repo)\n        self.tests = self._git_repo.new_file_repository(relative_path=TEST_CODES_FILE_REPO)\n        self.test_outputs = self._git_repo.new_file_repository(relative_path=TEST_OUTPUTS_FILE_REPO)\n        self._srcs_path = None\n        self.code_files_exists()\n\n    def __str__(self):\n        repo_str = f\"ProjectRepo({self._git_repo.workdir})\"\n        docs_str = f\"Docs({self.docs.all_files})\"\n        srcs_str = f\"Srcs({self.srcs.all_files})\"\n        return f\"{repo_str}\\n{docs_str}\\n{srcs_str}\"\n\n    @property\n    async def requirement(self):\n        return await self.docs.get(filename=REQUIREMENT_FILENAME)","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/utils/project_repo.py#L81-L117","documentation":"Raised by ProjectRepo.__init__: the constructor accepts only a str/Path (treated as the local git path, wrapped into GitRepository) or an existing GitRepository instance; anything else (None, a Config object, a repo object of another type) hits the else-branch and is rejected.","triggerScenarios":"ProjectRepo(None) when an upstream variable is unset; ProjectRepo(ctx.git_repo) where git_repo was never initialized; passing a string-like custom object that is not str/Path.","commonSituations":"Contexts where the git repository was expected to be initialized earlier in the flow (e.g. a Context/Env whose git_repo attribute is None), or API changes where callers now must pass a GitRepository rather than something else.","solutions":["Pass a valid path: ProjectRepo('/path/to/repo') or ProjectRepo(Path(...)).","Or pass the GitRepository object itself: ProjectRepo(ctx.git_repo) after ensuring it is not None.","If the value may be None, initialize a GitRepository first: ProjectRepo(GitRepository(local_path=Path.cwd()))."],"exampleFix":"# before\nrepo = ProjectRepo(ctx.git_repo)  # ctx.git_repo is None -> ValueError\n\n# after\nfrom metagpt.utils.git_repository import GitRepository\nrepo = ProjectRepo(ctx.git_repo or GitRepository(local_path=Path.cwd()))","handlingStrategy":"type-guard","validationCode":"from pathlib import Path\nfrom metagpt.utils.git_repository import GitRepository\nassert isinstance(root, (str, Path, GitRepository)) and root is not None, \\\n    'ProjectRepo root must be str/Path/GitRepository'","typeGuard":"def is_project_repo_root(root) -> bool:\n    return isinstance(root, (str, Path)) or root.__class__.__name__ == 'GitRepository'","tryCatchPattern":"try:\n    repo = ProjectRepo(root)\nexcept ValueError:\n    repo = ProjectRepo(Path.cwd())  # sensible default local path","preventionTips":["Initialize Context.git_repo before passing it to ProjectRepo.","Pass explicit absolute paths in scripts/tests.","Guard optional values: `root or Path.cwd()`."],"tags":["metagpt","repository","type-validation"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}