github/spec-kit · error · SystemExit
ERROR: SPECIFY_INIT_DIR does not point to an existing direct
Error message
ERROR: SPECIFY_INIT_DIR does not point to an existing directory: {raw} What it means
In _validate_safe_shared_directory(), an existing component resolves outside the resolved project root. Unlike the symlink checks, this catches non-symlink redirections — junctions, bind mounts, or paths whose canonical location leaves the root once resolved — and refuses to proceed with shared-infra operations through them.
Source
Thrown at scripts/python/common.py:43
parent = current.parent
if parent == current:
return None
current = parent
def resolve_specify_init_dir() -> Path:
raw = os.environ.get("SPECIFY_INIT_DIR", "")
candidate = Path(raw)
if not candidate.is_absolute():
candidate = Path.cwd() / candidate
try:
init_root = candidate.resolve(strict=True)
except OSError:
print(
f"ERROR: SPECIFY_INIT_DIR does not point to an existing directory: {raw}",
file=sys.stderr,
)
raise SystemExit(1)
if not init_root.is_dir():
print(
f"ERROR: SPECIFY_INIT_DIR does not point to an existing directory: {raw}",
file=sys.stderr,
)
raise SystemExit(1)
if not (init_root / ".specify").is_dir():
print(
"ERROR: SPECIFY_INIT_DIR is not a Spec Kit project "
f"(no .specify/ directory): {init_root}",
file=sys.stderr,
)
raise SystemExit(1)
return init_root
def get_repo_root(script_file: Path | None = None) -> Path:
if os.environ.get("SPECIFY_INIT_DIR"):View on GitHub (pinned to bf88c9f9a8)
Solutions
- Pass project_path pre-resolved: Path(project).resolve()
- Replace junctions/mounts inside the tree with real directories
- Move the project to a native filesystem location without redirect semantics
- Debug by printing resolve() of each parent vs the root to identify the escaping component
Example fix
# before
run(Path('C:/proj')) # with a junction inside .specify
# after
run(Path('C:/proj').resolve()) # and: rmdir junction, mkdir real dir Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
root = project_path.resolve()
for parent in rel_dir.parents:
p = root / parent
if p.exists():
assert p.resolve().is_relative_to(root), f'{p} escapes root after resolve' Try / catch
try:
_validate_safe_shared_directory(project_path, directory)
except ValueError as e:
if 'escapes project root' in str(e):
_validate_safe_shared_directory(Path(project_path).resolve(), directory)
else:
raise Prevention
- Replace Windows junctions/bind mounts inside the tree with real directories
- Pass resolved roots; avoid /mnt/c and symlinked temp dirs as project locations
- Debug escaping components with a loop printing resolve() per parent
When it happens
Trigger: A parent component is a Windows junction, bind mount, or mount point that resolve() relocates outside root; or root was passed non-resolved and a component canonicalizes differently (macOS /tmp, WSL host mounts).
Common situations: Windows directory junctions created by mklink /J to save disk; WSL accessing /mnt/c paths; devcontainer bind mounts; project living under symlinked temp dirs.
Related errors
- Error: --number must be a non-negative integer
- ERROR: SPECIFY_INIT_DIR is not a Spec Kit project (no .speci
- Error: --short-name requires a value
- Error: branch_template must not place {slug} before {number}
- Error: branch_template must put {number}- at the start of th
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/534df8781598c1ef.
Report an issue: GitHub.