{"record":{"id":"48ce4b4089e7b374","repo":"github/spec-kit","slug":"unknown-component-kind-kind","errorCode":null,"errorMessage":"Unknown component kind '{kind}'.","messagePattern":"Unknown component kind '(.+?)'\\.","errorType":"exception","errorClass":"BundlerError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/bundler/services/primitives.py","lineNumber":112,"sourceCode":"    def refresh(self, component: ComponentRef) -> None:\n        pass\n\n    def remove(self, component: ComponentRef) -> None:\n        pass\n\n\ndef primitive_manager(\n    kind: str, project_root: Path, *, allow_network: bool = True\n) -> _KindManager:\n    if kind == \"presets\":\n        return _PresetKindManager(project_root, allow_network)\n    if kind == \"extensions\":\n        return _ExtensionKindManager(project_root, allow_network)\n    if kind == \"workflows\":\n        return _WorkflowKindManager(project_root, allow_network)\n    if kind == \"steps\":\n        return _StepKindManager(project_root, allow_network)\n    raise BundlerError(f\"Unknown component kind '{kind}'.\")\n\n\n@contextlib.contextmanager\ndef _chdir(path: Path):\n    \"\"\"Temporarily switch the working directory.\n\n    The delegated workflow/step command callables resolve the project via\n    ``Path.cwd()``; this makes that resolution land on *path*.\n    \"\"\"\n    previous = Path.cwd()\n    os.chdir(path)\n    try:\n        yield\n    finally:\n        os.chdir(previous)\n\n\ndef _delegate_command(action: str, label: str, call) -> None:","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/bundler/services/primitives.py#L94-L130","documentation":"primitive_manager() dispatches component installs by kind and only recognizes the strings 'presets', 'extensions', 'workflows', and 'steps'. Any other kind string reaches the fall-through and raises immediately, before any manager is constructed.","triggerScenarios":"A bundle.yml or caller-supplied ComponentRef with kind set to something else — e.g. singular forms ('preset', 'extension'), 'skills', 'commands', or a typo — passed into primitive_manager() or into a bundle install that routes components by kind.","commonSituations":"Bundle authors using singular kind names; manifests written against a different tool's schema; new component types expected after a spec-kit upgrade that this version does not support; simple typos.","solutions":["Change the kind in bundle.yml to one of the exact plural forms: presets, extensions, workflows, steps.","Check for typos and singular/plural confusion ('preset' → 'presets').","If you genuinely need a new component type, upgrade specify_cli — the supported set may have grown in a newer release.","Run `specify bundle validate` to catch this before install."],"exampleFix":"# before (bundle.yml)\ncomponents:\n  - kind: preset\n    id: my-preset\n\n# after\ncomponents:\n  - kind: presets\n    id: my-preset","handlingStrategy":"type-guard","validationCode":"SUPPORTED_KINDS = {\"presets\", \"extensions\", \"workflows\", \"steps\"}\nassert component.kind in SUPPORTED_KINDS, f\"kind must be one of {sorted(SUPPORTED_KINDS)}\"","typeGuard":"def is_supported_kind(kind: str) -> bool:\n    \"\"\"Type guard matching primitive_manager()'s dispatch table.\"\"\"\n    return kind in {\"presets\", \"extensions\", \"workflows\", \"steps\"}","tryCatchPattern":"from specify_cli.bundler.core import BundlerError\n\ntry:\n    manager = primitive_manager(kind, project_root)\nexcept BundlerError as exc:\n    if \"Unknown component kind\" in str(exc):\n        raise ValueError(f\"fix bundle.yml: {exc}\") from exc","preventionTips":["Use the plural kind names (presets/extensions/workflows/steps) exactly.","Validate manifests with `specify bundle validate` before install to catch bad kinds early.","When upgrading specify_cli, re-check the supported kind set if you rely on new component types."],"tags":["bundler","dispatch","kind","manifest"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}