github/spec-kit · error · ValueError
{type(self).__name__}.config is missing required 'folder' en
Error message
{type(self).__name__}.config is missing required 'folder' entry. What it means
Companion check in SkillsIntegration.skills_dest(): config exists but has no 'folder' key (or it is empty/None). The folder value determines where speckit-<name>/SKILL.md files are installed, so a missing one cannot be defaulted safely. Like its sibling, this is a subclass-authoring error surfaced at install time.
Source
Thrown at src/specify_cli/integrations/base.py:1601
if model:
args.extend(["--model", model])
if output_json:
args.extend(["--output-format", "json"])
return args
def skills_dest(self, project_root: Path) -> Path:
"""Return the absolute path to the skills output directory.
Derived from ``config["folder"]`` and the configured
``commands_subdir`` (defaults to ``"skills"``).
Raises ``ValueError`` when ``config`` or ``folder`` is missing.
"""
if not self.config:
raise ValueError(f"{type(self).__name__}.config is not set.")
folder = self.config.get("folder")
if not folder:
raise ValueError(
f"{type(self).__name__}.config is missing required 'folder' entry."
)
subdir = self.config.get("commands_subdir", "skills")
return project_root / folder / subdir
def build_command_invocation(self, command_name: str, args: str = "") -> str:
"""Build the agent's native invocation for a hyphenated skill name."""
stem = command_name
if stem.startswith("speckit."):
stem = stem[len("speckit."):]
prefix = "$" if is_dollar_skills_agent(self.key, True) else "/"
invocation = prefix + "speckit-" + stem.replace(".", "-")
if args:
invocation = f"{invocation} {args}"
return invocation
@staticmethodView on GitHub (pinned to bf88c9f9a8)
Solutions
- Add a non-empty project-relative folder entry, e.g. "folder": ".my-agent/".
- Compare against a known-good skills integration (e.g. claude or codex in this repo) for the exact required keys.
- Validate config keys in the integration's test file so the error surfaces in CI, not at install.
Example fix
# before
config = {"name": "My Agent", "commands_subdir": "skills"}
# after
config = {"name": "My Agent", "folder": ".my-agent/", "commands_subdir": "skills"} Defensive patterns
Strategy: type-guard
Validate before calling
def has_folder_key(integration) -> bool:
return bool((getattr(integration, "config", None) or {}).get("folder")) Type guard
def skills_config_valid(integration) -> bool:
cfg = getattr(integration, "config", None) or {}
return isinstance(cfg, dict) and bool(cfg.get("folder")) Try / catch
try:
integration.skills_dest(project_root)
except ValueError as exc:
if "missing required 'folder'" in str(exc):
raise SystemExit("add a non-empty project-relative 'folder' to config") from None
raise Prevention
- Spell the key exactly 'folder' and give it a non-empty relative path like '.my-agent/'.
- Copy the full config dict shape from an existing skills integration (claude, codex).
- Cover config completeness in the integration's dedicated test file.
When it happens
Trigger: A SkillsIntegration subclass whose config dict omits 'folder' or sets it to "" / None; a typo like "folders" or "dir" instead of "folder".
Common situations: Hand-writing a new skills integration from memory and misspelling the key; copying a Markdown integration's config and dropping the folder line during trimming.
Related errors
- {type(self).__name__}.config is not set.
- Skills destination {skills_dir} escapes project root {projec
- {env_name} is not parseable as a POSIX-quoted command line (
- Integration destination {dest} escapes project root {project
- manifest.project_root ({manifest.project_root}) does not mat
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/3e1365cc473a5562.
Report an issue: GitHub.