github/spec-kit · error · ValueError
Integration manifest path is not a file: {label}
Error message
Integration manifest path is not a file: {label} What it means
Raised when the destination manifest path exists but is not a regular file (e.g. it is a directory, FIFO, or device). The manifest writer only replaces regular files and refuses anything else.
Source
Thrown at src/specify_cli/integrations/manifest.py:97
raise ValueError(f"Integration manifest directory escapes project root: {label}") from None
continue
current.mkdir()
try:
current.resolve().relative_to(root_resolved)
except (OSError, ValueError):
raise ValueError(f"Integration manifest directory escapes project root: {label}") from None
def _ensure_safe_manifest_destination(root: Path, path: Path) -> None:
"""Refuse manifest writes that would escape the project or follow symlinks."""
root_resolved = root.resolve()
_ensure_safe_manifest_directory(root, path.parent)
label = _manifest_path_label(root, path)
if path.is_symlink():
raise ValueError(f"Refusing to overwrite symlinked integration manifest path: {label}")
if path.exists():
if not path.is_file():
raise ValueError(f"Integration manifest path is not a file: {label}")
try:
path.resolve().relative_to(root_resolved)
except (OSError, ValueError):
raise ValueError(f"Integration manifest path escapes project root: {label}") from None
class IntegrationManifest:
"""Tracks files installed by a single integration.
Parameters:
key: Integration identifier (e.g. ``"copilot"``).
project_root: Absolute path to the project directory.
version: CLI version string recorded in the manifest.
resolve_project_root: Resolve ``project_root`` before using it.
"""
def __init__(
self,View on GitHub (pinned to bf88c9f9a8)
Solutions
- Check the path from the error message: ls -la .specify/integrations/<key>.manifest.json
- If it is a directory, remove it (rm -rf) and re-run the specify command
- If it holds wanted data, move it aside first
Example fix
# before .specify/integrations/claude.manifest.json/ # a directory # after rm -rf .specify/integrations/claude.manifest.json # then re-run install
Defensive patterns
Strategy: validation
Validate before calling
mp = manifest.manifest_path
assert not (mp.exists() and not mp.is_file()), f"non-file at {mp}" Try / catch
try:
manifest.save()
except ValueError as exc:
if "not a file" in str(exc):
shutil.rmtree(manifest.manifest_path, ignore_errors=True)
manifest.save()
else:
raise Prevention
- Audit restored backups for directories where files belong
- Verify with ls -la after restore scripts
- Avoid cp/rsync inversions when moving .specify around
When it happens
Trigger: A directory named <key>.manifest.json exists under .specify/integrations when save() runs — usually the residue of a bad copy, a template that rendered a directory where a file belongs, or an interrupted install that left a partial tree.
Common situations: Restoring from a backup that dropped the trailing filename and created a directory; rsync/cp mistakes; concurrent or half-failed installs.
Related errors
- Integration manifest directory path is not a directory: {lab
- No bundle.yml found in '{bundle_dir}'.
- No bundle.yml found in '{candidate}'.
- No bundle.yml found at '{target}'.
- No extension.yml found in {source_path}
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/355f22a3cfe67b67.
Report an issue: GitHub.