{"record":{"id":"082b85b10206aeb1","repo":"github/spec-kit","slug":"invalid-install-policy-value-must-be-one-of","errorCode":null,"errorMessage":"Invalid install_policy '{value}' (must be one of {[p.value for p in cls]}).","messagePattern":"Invalid install_policy '(.+?)' \\(must be one of (.+?)\\)\\.","errorType":"exception","errorClass":"BundlerError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/bundler/models/catalog.py","lineNumber":35,"sourceCode":"CONFIG_FILENAME = \"bundle-catalogs.yml\"\n# Supported bundle-catalogs.yml schema (major version). Both readers of the\n# file — this module's _merge_config and commands_impl/catalog_config._read —\n# reject an unsupported major version so a file written by a newer/incompatible\n# Spec Kit fails fast instead of being parsed under the wrong assumptions.\nCONFIG_SCHEMA_VERSION = \"1.0\"\n\n\nclass InstallPolicy(str, Enum):\n    INSTALL_ALLOWED = \"install-allowed\"\n    DISCOVERY_ONLY = \"discovery-only\"\n\n    @classmethod\n    def parse(cls, value: Any) -> \"InstallPolicy\":\n        text = str(value or \"\").strip()\n        for policy in cls:\n            if policy.value == text:\n                return policy\n        raise BundlerError(\n            f\"Invalid install_policy '{value}' \"\n            f\"(must be one of {[p.value for p in cls]}).\"\n        )\n\n\nclass Scope(str, Enum):\n    PROJECT = \"project\"\n    USER = \"user\"\n    BUILTIN = \"built-in\"\n\n\n# Built-in default stack (used when no project/user config overrides it).\nBUILTIN_DEFAULT_STACK: tuple[dict[str, Any], ...] = (\n    {\"id\": \"default\", \"url\": \"builtin://default\", \"priority\": 1,\n     \"install_policy\": InstallPolicy.INSTALL_ALLOWED.value},\n    {\"id\": \"community\", \"url\": \"builtin://community\", \"priority\": 20,\n     \"install_policy\": InstallPolicy.DISCOVERY_ONLY.value},\n)","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/bundler/models/catalog.py#L17-L53","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"# before\nadd_source(root, \"src\", url, priority=5, policy=\"allow-install\")  # raises\n\n# after\nadd_source(root, \"src\", url, priority=5, policy=\"install-allowed\")","handlingStrategy":"validation","validationCode":"from specify_cli.bundler.models.catalog import InstallPolicy\n\nVALID_POLICIES = {p.value for p in InstallPolicy}\nif user_policy not in VALID_POLICIES:\n    raise ValueError(f\"policy must be one of {sorted(VALID_POLICIES)}\")\nadd_source(root, sid, url, priority=10, policy=user_policy)","typeGuard":"def is_install_policy(value: str) -> bool:\n    return isinstance(value, str) and value in {p.value for p in InstallPolicy}","tryCatchPattern":"try:\n    InstallPolicy.parse(policy)\nexcept BundlerError as e:\n    # surface valid options to the user from the error text\n    show(f\"Invalid policy: {e}\")","preventionTips":["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'."],"tags":["bundler","catalog","validation","enum","install-policy"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}