github/spec-kit · error · BundlerError
Invalid install_policy '{value}' (must be one of {[p.value f
Error message
Invalid install_policy '{value}' (must be one of {[p.value for p in cls]}). What it means
Raised by InstallPolicy.parse() when the supplied install_policy string does not equal any enum value ('install-allowed' or 'discovery-only'). Parsing is exact-match on the stripped string, so case variants, abbreviations, or legacy values are rejected. This guards catalog configuration from silently falling back to a permissive install policy.
Source
Thrown at src/specify_cli/bundler/models/catalog.py:35
CONFIG_FILENAME = "bundle-catalogs.yml"
# Supported bundle-catalogs.yml schema (major version). Both readers of the
# file — this module's _merge_config and commands_impl/catalog_config._read —
# reject an unsupported major version so a file written by a newer/incompatible
# Spec Kit fails fast instead of being parsed under the wrong assumptions.
CONFIG_SCHEMA_VERSION = "1.0"
class InstallPolicy(str, Enum):
INSTALL_ALLOWED = "install-allowed"
DISCOVERY_ONLY = "discovery-only"
@classmethod
def parse(cls, value: Any) -> "InstallPolicy":
text = str(value or "").strip()
for policy in cls:
if policy.value == text:
return policy
raise BundlerError(
f"Invalid install_policy '{value}' "
f"(must be one of {[p.value for p in cls]})."
)
class Scope(str, Enum):
PROJECT = "project"
USER = "user"
BUILTIN = "built-in"
# Built-in default stack (used when no project/user config overrides it).
BUILTIN_DEFAULT_STACK: tuple[dict[str, Any], ...] = (
{"id": "default", "url": "builtin://default", "priority": 1,
"install_policy": InstallPolicy.INSTALL_ALLOWED.value},
{"id": "community", "url": "builtin://community", "priority": 20,
"install_policy": InstallPolicy.DISCOVERY_ONLY.value},
)View on GitHub (pinned to bf88c9f9a8)
Solutions
- Use exactly one of the enum strings: 'install-allowed' or 'discovery-only' (lowercase, hyphenated).
- If loading user input, validate against [p.value for p in InstallPolicy] before calling parse/add_source.
- Fix the install_policy field in the catalog config file (project .specify catalog config) to a legal value.
- For 'unspecified', omit the parameter only if the API you are calling applies its own default — never pass an empty string.
Example fix
# before add_source(root, "src", url, priority=5, policy="allow-install") # raises # after add_source(root, "src", url, priority=5, policy="install-allowed")
Defensive patterns
Strategy: validation
Validate before calling
from specify_cli.bundler.models.catalog import InstallPolicy
VALID_POLICIES = {p.value for p in InstallPolicy}
if user_policy not in VALID_POLICIES:
raise ValueError(f"policy must be one of {sorted(VALID_POLICIES)}")
add_source(root, sid, url, priority=10, policy=user_policy) Type guard
def is_install_policy(value: str) -> bool:
return isinstance(value, str) and value in {p.value for p in InstallPolicy} Try / catch
try:
InstallPolicy.parse(policy)
except BundlerError as e:
# surface valid options to the user from the error text
show(f"Invalid policy: {e}") Prevention
- Offer InstallPolicy values as a dropdown/choices list in tooling instead of free text.
- Never pass empty strings or None as policy.
- Pin config files to the enum spellings: 'install-allowed', 'discovery-only'.
When it happens
Trigger: Calling add_source(..., policy='allow'), policy='Install-Allowed', or policy='' (empty); loading a catalog config file whose install_policy value predates or misspells the current enum; passing None (str(None or '') becomes '' and matches nothing).
Common situations: Hand-edited catalog config files with typos; older config files written against different policy names; scripts passing boolean-ish or abbreviated values; copy-paste from docs of a different tool version.
Related errors
- Malformed catalog config at {path}: expected a mapping at th
- Malformed catalog config at {path}: 'catalogs' must be a lis
- Malformed catalog config at {path}: each catalog entry must
- A catalog url is required.
- Invalid catalog url: '{url}'.
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/082b85b10206aeb1.
Report an issue: GitHub.