{"record":{"id":"f0c88758a696dc75","repo":"github/spec-kit","slug":"invalid-template-file-path-file-path-must-be","errorCode":null,"errorMessage":"Invalid template file path '{file_path}': must be a relative path within the preset directory","messagePattern":"Invalid template file path '(.+?)': must be a relative path within the preset directory","errorType":"validation","errorClass":"PresetValidationError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/presets/__init__.py","lineNumber":445,"sourceCode":"            # relative_extension_path_violation().\n            for field in (\"type\", \"name\", \"file\"):\n                if not isinstance(tmpl[field], str):\n                    raise PresetValidationError(\n                        f\"Invalid template {field}: expected a string, \"\n                        f\"got {type(tmpl[field]).__name__}\"\n                    )\n\n            if tmpl[\"type\"] not in VALID_PRESET_TEMPLATE_TYPES:\n                raise PresetValidationError(\n                    f\"Invalid template type '{tmpl['type']}': \"\n                    f\"must be one of {sorted(VALID_PRESET_TEMPLATE_TYPES)}\"\n                )\n\n            # Validate file path safety: must be relative, no parent traversal\n            file_path = tmpl[\"file\"]\n            normalized = os.path.normpath(file_path)\n            if os.path.isabs(normalized) or normalized.startswith(\"..\"):\n                raise PresetValidationError(\n                    f\"Invalid template file path '{file_path}': \"\n                    \"must be a relative path within the preset directory\"\n                )\n\n            # Validate strategy field (optional, defaults to \"replace\")\n            strategy = tmpl.get(\"strategy\", \"replace\")\n            if not isinstance(strategy, str):\n                raise PresetValidationError(\n                    f\"Invalid strategy value: must be a string, \"\n                    f\"got {type(strategy).__name__}\"\n                )\n            strategy = strategy.lower()\n            # Persist normalized value so downstream code sees lowercase\n            if \"strategy\" in tmpl:\n                tmpl[\"strategy\"] = strategy\n            if strategy not in VALID_PRESET_STRATEGIES:\n                raise PresetValidationError(\n                    f\"Invalid strategy '{strategy}': \"","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/presets/__init__.py#L427-L463","documentation":"Error \"Invalid template file path '{file_path}': must be a relative path within the preset directory\" thrown in github/spec-kit.","triggerScenarios":"Thrown at src/specify_cli/presets/__init__.py:445 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use a relative template file path that stays within the preset directory (no '..')."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}