github/spec-kit · error · ValueError
No runnable script variant for this platform: requested {req
Error message
No runnable script variant for this platform: requested {requested!r}; available: {available} What it means
IntegrationBase.select_script_variant picks the script variant (sh/ps/py) for a command template. It first honors the requested variant if present in script_commands (the variants the template's scripts: frontmatter actually provides); otherwise it falls back to the platform native variant (ps on Windows, sh elsewhere), then the cross-platform py, and only then gives up with this error. Seeing it means script_commands contained none of the viable candidates — i.e. the template declared no (or only the wrong) script variants.
Source
Thrown at src/specify_cli/integrations/base.py:731
"""Select the requested variant or a runnable platform fallback."""
if isinstance(requested, str) and requested in script_commands:
return requested
platform_variant = (
"ps" if platform.system().lower().startswith("win") else "sh"
)
secondary_variant = "sh" if platform_variant == "ps" else "ps"
fallbacks = (
(platform_variant, "py")
if requested == "py"
else (platform_variant, secondary_variant, "py")
)
for candidate in fallbacks:
if candidate in script_commands:
return candidate
available = ", ".join(sorted(script_commands)) or "none"
raise ValueError(
"No runnable script variant for this platform: "
f"requested {requested!r}; available: {available}"
)
@staticmethod
def _interpreter_runs(path: str) -> bool:
"""Return True when *path* executes as a Python interpreter.
Runs isolated (``-I``) without ``site`` (``-S``) and discards
I/O so the probe is a fast liveness check that cannot trigger
``sitecustomize``/user startup hooks.
"""
try:
return (
subprocess.run(
[path, "-I", "-S", "-c", ""],
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,View on GitHub (pinned to bf88c9f9a8)
Solutions
- Add a complete scripts: frontmatter to the template with sh, ps, and py entries (all three are required by the parity rule).
- Check the reported 'available:' list — it shows exactly which variant keys the template did declare; fix typos like 'bash' -> 'sh'.
- If the template genuinely needs no script, route it through the template path that skips select_script_variant instead of calling it unconditionally.
Example fix
# before (templates/commands/my-command.md) --- description: "Broken" --- # after --- description: "Fixed" scripts: sh: scripts/bash/my-command.sh ps: scripts/powershell/my-command.ps1 py: scripts/python/my_command.py ---
Defensive patterns
Strategy: validation
Validate before calling
from specify_cli.integrations.base import IntegrationBase
variant = IntegrationBase.select_script_variant(
requested, {k: v for k, v in script_commands.items()}
) # raises with the 'available:' list if unsatisfiable — call it early to fail fast Type guard
def has_runnable_variant(script_commands: dict[str, str]) -> bool:
import platform
native = "ps" if platform.system().lower().startswith("win") else "sh"
secondary = "sh" if native == "ps" else "ps"
return bool(script_commands) and any(
v in script_commands for v in (native, secondary, "py")
) Try / catch
try:
variant = IntegrationBase.select_script_variant(requested, script_commands)
except ValueError as exc:
raise SystemExit(
f"template provides no runnable script variants ({exc}); "
"add sh/ps/py entries to its scripts: frontmatter"
) from None Prevention
- Always author command templates with the full scripts: frontmatter (sh, ps, py).
- Keep the three script variants behaviorally identical per the parity rule so any fallback works.
- Validate templates in CI: every template that invokes a script must declare all three variants.
When it happens
Trigger: A command template whose scripts: frontmatter is missing or lists no sh/ps/py entries that match the platform fallbacks — e.g. only a 'ps' entry while running on Linux is fine (secondary fallback), but an empty or typo'd variant key set ('shell', 'bash') yields an empty/foreign script_commands dict; requesting a variant like 'py' when the template provides only variants outside the fallback chain.
Common situations: Custom or forked command templates that omit the scripts: frontmatter required by the parity rule; templates that use non-canonical keys; a template intentionally having no script (constitution/specify style) being processed through a path that expects one.
Related errors
- Failed to parse preset manifest {manifest_path}: {exc}
- Unknown template composition strategy '{strategy}' in {path}
- Each entry in 'provides.{section}' must be a mapping
- Wrap layer {path} is missing {placeholder}
- Failed to read template layer for '{template_name}': {exc}
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/20f006fa39ac1562.
Report an issue: GitHub.