diff --git a/src/specify_cli/presets/__init__.py b/src/specify_cli/presets/__init__.py index de4116228e..32d59a4b8b 100644 --- a/src/specify_cli/presets/__init__.py +++ b/src/specify_cli/presets/__init__.py @@ -5225,7 +5225,7 @@ def _find_in_subdirs(base_dir: Path) -> Optional[Path]: fm_strategy = fm_data.get("strategy") if isinstance(fm_strategy, str) and fm_strategy.lower() in VALID_PRESET_STRATEGIES: strategy = fm_strategy.lower() - except (yaml.YAMLError, OSError): + except (UnicodeDecodeError, yaml.YAMLError, OSError): # Best-effort legacy frontmatter parsing: keep default # strategy ("replace") when content is unreadable/invalid. pass diff --git a/tests/test_presets.py b/tests/test_presets.py index dbf6ac4ccb..206196d71e 100644 --- a/tests/test_presets.py +++ b/tests/test_presets.py @@ -11513,6 +11513,24 @@ def test_resolve_content_rewrites_extension_base_subdir_paths( class TestCollectAllLayers: """Test PresetResolver.collect_all_layers() method.""" + def test_non_utf8_legacy_command_keeps_replace_strategy(self, project_dir): + presets_dir = project_dir / ".specify" / "presets" + command_path = ( + presets_dir / "legacy-pack" / "commands" / "speckit.legacy.md" + ) + command_path.parent.mkdir(parents=True) + command_path.write_bytes(b"\xff\xfe") + PresetRegistry(presets_dir).add( + "legacy-pack", {"version": "1.0.0", "priority": 10} + ) + + layers = PresetResolver(project_dir).collect_all_layers( + "speckit.legacy", "command" + ) + + assert layers[0]["path"] == command_path + assert layers[0]["strategy"] == "replace" + def test_single_core_layer(self, project_dir): """Test collecting layers with only core template.""" resolver = PresetResolver(project_dir)