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 HermesIntegration.setup() (src/specify_cli/integrations/hermes/__init__.py:100) when the manifest's recorded project_root does not equal the resolved project_root argument. Hermes installs into a global skills directory but still creates a project-local marker, so it performs the same standard manifest/root binding check as other integrations before writing anything.
Source
Thrown at src/specify_cli/integrations/hermes/__init__.py:100
) -> list[Path]:
"""Install command templates as global Hermes skills.
Writes each skill directly to
``~/.hermes/skills/speckit-<name>/SKILL.md`` where Hermes
discovers them at runtime. No project-local SKILL.md copies are
created — the global directory is the single source of truth.
A project-local marker (``.hermes/skills/`` empty) is created
so extension commands (e.g. git) can detect Hermes as an active
integration.
"""
templates = self.list_command_templates()
if not templates:
return []
# Safety check: verify manifest project_root matches (standard pattern)
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})"
)
script_type = opts.get("script_type", "sh")
arg_placeholder = (
self.registrar_config.get("args", "$ARGUMENTS")
if self.registrar_config
else "$ARGUMENTS"
)
global_skills_dir = self._hermes_home_skills_dir()
global_skills_dir.mkdir(parents=True, exist_ok=True)
created: list[Path] = []
for src_file in templates:
raw = src_file.read_text(encoding="utf-8")View on GitHub (pinned to bf88c9f9a8)
Solutions
- Create the manifest with project_root.resolve() and pass the identical resolved root to setup().
- Create a fresh manifest per project; never reuse across roots.
- Prefer 'specify init --integration hermes', which wires the manifest correctly.
Example fix
# before
manifest = IntegrationManifest(project_root=Path("~/proj").expanduser())
HermesIntegration().setup(Path("/Users/u/proj"), manifest)
# after
root = Path("/Users/u/proj").resolve()
manifest = IntegrationManifest(project_root=root)
HermesIntegration().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
- Resolve project_root once and use it for both the manifest and setup().
- Don't carry manifests across directory changes or projects.
- Let 'specify init --integration hermes' manage manifest lifecycle.
When it happens
Trigger: HermesIntegration().setup(project_root, manifest) where manifest.project_root differs from project_root.resolve() — different directory, another project's manifest, or an unresolved/symlinked spelling of the same directory.
Common situations: Reusing a manifest created before changing directories; /tmp vs /private/tmp symlink differences on macOS; automated harnesses mixing tmp_path and its resolved form.
Related errors
- manifest.project_root ({manifest.project_root}) does not mat
- 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
- Integration destination {dest} escapes project root {project
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/081a7eac541b063c.
Report an issue: GitHub.