github/spec-kit · error · ValueError
manifest.project_root ({manifest.project_root}) does not mat
Error message
manifest.project_root ({manifest.project_root}) does not match project_root ({project_root_resolved}) What it means
Raised by ForgeIntegration.setup() (src/specify_cli/integrations/forge/__init__.py:124) when the IntegrationManifest's recorded project_root differs from the resolved project_root argument. All custom setup() implementations in spec-kit verify manifest-to-root binding before writing, so a manifest created for one location (or an unresolved/symlinked variant of it) is rejected here.
Source
Thrown at src/specify_cli/integrations/forge/__init__.py:124
def setup(
self,
project_root: Path,
manifest: IntegrationManifest,
parsed_options: dict[str, Any] | None = None,
**opts: Any,
) -> list[Path]:
"""Install Forge commands with custom processing.
Extends MarkdownIntegration.setup() to inject Forge-specific transformations
after standard template processing.
"""
templates = self.list_command_templates()
if not templates:
return []
project_root_resolved = project_root.resolve()
if manifest.project_root != project_root_resolved:
raise ValueError(
f"manifest.project_root ({manifest.project_root}) does not match "
f"project_root ({project_root_resolved})"
)
dest = self.commands_dest(project_root).resolve()
try:
dest.relative_to(project_root_resolved)
except ValueError as exc:
raise ValueError(
f"Integration destination {dest} escapes "
f"project root {project_root_resolved}"
) from exc
dest.mkdir(parents=True, exist_ok=True)
script_type = opts.get("script_type", "sh")
arg_placeholder = self.registrar_config.get("args", "{{parameters}}")
created: list[Path] = []
View on GitHub (pinned to bf88c9f9a8)
Solutions
- Create the manifest with the identical resolved root: manifest = IntegrationManifest(project_root=project_root.resolve()).
- Pass the same Path object (or an identically resolved one) to setup().
- Never share a manifest instance between different project roots.
- Prefer the specify CLI (specify init --integration forge) which constructs the manifest correctly.
Example fix
# before
manifest = IntegrationManifest(project_root=Path.cwd())
ForgeIntegration().setup(Path("/home/u/proj"), manifest)
# after
root = Path("/home/u/proj").resolve()
manifest = IntegrationManifest(project_root=root)
ForgeIntegration().setup(root, manifest) Defensive patterns
Strategy: validation
Validate before calling
root = project_root.resolve()
if manifest.project_root != root:
manifest = IntegrationManifest(project_root=root) Try / catch
try:
integration.setup(root, manifest)
except ValueError as e:
if "manifest.project_root" in str(e):
manifest = IntegrationManifest(project_root=root.resolve())
integration.setup(root, manifest)
else:
raise Prevention
- Construct the manifest from the same resolved root passed to setup().
- Beware symlinked roots (/tmp vs /private/tmp) — resolve() early.
- Create a fresh manifest per project; never reuse across projects.
When it happens
Trigger: Calling ForgeIntegration().setup(project_root, manifest) where manifest was instantiated with a different or non-equivalently-resolved root; e.g. manifest built from '.' while setup receives an absolute path, or the manifest object belongs to another project entirely.
Common situations: Test harnesses that create manifests in tmp_path but call setup with tmp_path_resolved variants; reusing one manifest across nested sub-projects; symlinked working directories (/tmp vs /private/tmp) making resolve() produce different strings.
Related errors
- manifest.project_root ({manifest.project_root}) does not mat
- Integration destination {dest} escapes project root {project
- manifest.project_root ({manifest.project_root}) does not mat
- manifest.project_root ({manifest.project_root}) does not mat
- Integration destination {dest_resolved} escapes project root
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/6798a4bd7feb110e.
Report an issue: GitHub.