github/spec-kit · error · ValueError

Refusing to scaffold outside the repository root: {target}

Error message

Refusing to scaffold outside the repository root: {target}

What it means

Raised by _assert_safe_scaffold_target in integration_scaffold.py when the scaffold target file cannot be expressed as a relative path under project_root (Path.relative_to raises ValueError). This is the first of two 'outside the repository root' guards: it catches targets that are not lexically under the supplied root before any symlink resolution happens. The scaffold command refuses to write integration/test skeletons anywhere but inside the Spec Kit source tree.

Source

Thrown at src/specify_cli/integration_scaffold.py:183

                project_root / "src" / "specify_cli" / "integrations" / "__init__.py"
            ).is_file(),
            (project_root / "tests" / "integrations").is_dir(),
        )
    )


def _assert_safe_scaffold_target(project_root: Path, target: Path) -> None:
    """Refuse to scaffold through a symlinked path that could escape the repo.

    Walks each component of *target* under *project_root* and rejects any
    existing symlinked directory (or symlinked target), then confirms the
    write destination still resolves inside the repository root. Mirrors the
    symlink-aware guarding used for integration manifests.
    """
    try:
        rel = target.relative_to(project_root)
    except ValueError:
        raise ValueError(
            f"Refusing to scaffold outside the repository root: {target}"
        ) from None

    current = project_root
    for part in rel.parts:
        current = current / part
        if current.is_symlink():
            label = current.relative_to(project_root).as_posix()
            raise ValueError(f"Refusing to scaffold through symlinked path: {label}")

    root_resolved = project_root.resolve()
    try:
        target.parent.resolve().relative_to(root_resolved)
    except (OSError, ValueError):
        raise ValueError(
            f"Refusing to scaffold outside the repository root: {target}"
        ) from None

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Run the scaffold command from the actual Spec Kit repository root so project_root is the parent of src/specify_cli and tests/integrations.
  2. Pass project_root as the repo root (the directory containing src/specify_cli) rather than a subdirectory or a symlinked alias.
  3. If the checkout is symlinked, cd into the real (resolved) path or resolve project_root with Path.resolve() before calling scaffold_integration.

Example fix

# before
scaffold_integration(Path("~/repos/spec-kit-link").expanduser(), "my-agent", "markdown")
# after (use the real repo root)
root = Path("~/repos/spec-kit").expanduser().resolve()
scaffold_integration(root, "my-agent", "markdown")
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def safe_scaffold_target(project_root: Path, target: Path) -> bool:
    try:
        target.relative_to(project_root)
    except ValueError:
        return False
    return True

# before calling scaffold_integration:
root = root.resolve()
assert safe_scaffold_target(root, root / "src" / "specify_cli" / "integrations" / pkg)

Try / catch

try:
    scaffold_integration(root, key, itype)
except ValueError as exc:
    if "outside the repository root" in str(exc):
        root = Path.cwd().resolve()  # re-anchor and retry once
    else:
        raise

Prevention

When it happens

Trigger: Calling scaffold_integration(project_root, key, type) with a target like project_root/'src'/'specify_cli'/'integrations'/pkg/'__init__.py' when project_root is not an ancestor of target: e.g. project_root was resolved to a different path (symlinked checkout), target was built from an absolute path from another tree, or the caller passed the wrong root.

Common situations: Running the scaffold CLI from a subdirectory so cwd-derived project_root disagrees with the target layout; a symlinked repo checkout where the naive root and the real root differ; CI checking out to a temp path while reusing cached absolute paths.

Related errors


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/774cf2f1f76c9358. Report an issue: GitHub.