File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -340,9 +340,12 @@ def list(self) -> Dict[str, dict]:
340340 from accidentally mutating nested internal registry state.
341341
342342 Returns:
343- Dictionary of extension_id -> metadata (deep copies)
343+ Dictionary of extension_id -> metadata (deep copies), empty dict if corrupted
344344 """
345- return copy .deepcopy (self .data ["extensions" ])
345+ extensions = self .data .get ("extensions" , {}) or {}
346+ if not isinstance (extensions , dict ):
347+ return {}
348+ return copy .deepcopy (extensions )
346349
347350 def is_installed (self , extension_id : str ) -> bool :
348351 """Check if extension is installed.
Original file line number Diff line number Diff line change @@ -350,9 +350,12 @@ def list(self) -> Dict[str, dict]:
350350 from accidentally mutating nested internal registry state.
351351
352352 Returns:
353- Dictionary of pack_id -> metadata (deep copies)
353+ Dictionary of pack_id -> metadata (deep copies), empty dict if corrupted
354354 """
355- return copy .deepcopy (self .data ["presets" ])
355+ packs = self .data .get ("presets" , {}) or {}
356+ if not isinstance (packs , dict ):
357+ return {}
358+ return copy .deepcopy (packs )
356359
357360 def list_by_priority (self , include_disabled : bool = False ) -> List [tuple ]:
358361 """Get all installed presets sorted by priority.
Original file line number Diff line number Diff line change @@ -520,6 +520,20 @@ def test_list_returns_deep_copy(self, temp_dir):
520520 internal = registry .data ["extensions" ]["test-ext" ]
521521 assert internal ["registered_commands" ] == {"claude" : ["cmd1" ]}
522522
523+ def test_list_returns_empty_dict_for_corrupted_registry (self , temp_dir ):
524+ """Test that list() returns empty dict when extensions is not a dict."""
525+ extensions_dir = temp_dir / "extensions"
526+ extensions_dir .mkdir ()
527+ registry = ExtensionRegistry (extensions_dir )
528+
529+ # Corrupt the registry - extensions is a list instead of dict
530+ registry .data ["extensions" ] = ["not" , "a" , "dict" ]
531+ registry ._save ()
532+
533+ # list() should return empty dict, not crash
534+ result = registry .list ()
535+ assert result == {}
536+
523537
524538# ===== ExtensionManager Tests =====
525539
Original file line number Diff line number Diff line change @@ -487,6 +487,20 @@ def test_list_returns_deep_copy(self, temp_dir):
487487 assert fresh ["version" ] == "1.0.0"
488488 assert fresh ["nested" ]["key" ] == "original"
489489
490+ def test_list_returns_empty_dict_for_corrupted_registry (self , temp_dir ):
491+ """Test that list() returns empty dict when presets is not a dict."""
492+ packs_dir = temp_dir / "packs"
493+ packs_dir .mkdir ()
494+ registry = PresetRegistry (packs_dir )
495+
496+ # Corrupt the registry - presets is a list instead of dict
497+ registry .data ["presets" ] = ["not" , "a" , "dict" ]
498+ registry ._save ()
499+
500+ # list() should return empty dict, not crash
501+ result = registry .list ()
502+ assert result == {}
503+
490504 def test_list_by_priority_excludes_disabled (self , temp_dir ):
491505 """Test that list_by_priority excludes disabled presets by default."""
492506 packs_dir = temp_dir / "packs"
You can’t perform that action at this time.
0 commit comments