fix(lora): skip a sidecar that is not UTF-8 instead of failing the load (#362)

Review follow-up on phase 4: read_lora_metadata caught JSONDecodeError but not
UnicodeDecodeError, so one non-UTF-8 sidecar failed the whole trigger-word
load (now logged with a traceback every retry) and the import review. It is
skipped like any unreadable sidecar. The relative preview_url DEBUG line uses
lazy formatting.
This commit is contained in:
Vito Sansevero
2026-10-26 23:00:59 -07:00
parent f020f1d751
commit ee8672a26c
5 changed files with 11 additions and 5 deletions
+1 -1
View File
@@ -577,7 +577,7 @@ def _preview_candidates(sidecar: Sidecar, metadata: Dict) -> Iterator[str]:
# LoraManager writes absolute paths; it would resolve a relative
# one against its working directory, not the sidecar folder.
logger.debug(
f"Relative preview_url skipped in {sidecar.metadata_path.name}"
"Relative preview_url skipped in %s", sidecar.metadata_path.name
)
base = sidecar.metadata_path.name[: -len(METADATA_SUFFIX)]
for suffix in PREVIEW_EXTENSIONS:
+1 -1
View File
@@ -368,7 +368,7 @@ def read_lora_metadata(metadata_path: Path) -> Optional[Dict]:
try:
with open(metadata_path, "r", encoding="utf-8") as f:
return json.load(f)
except (json.JSONDecodeError, OSError) as e:
except (ValueError, OSError) as e: # JSONDecodeError, UnicodeDecodeError
logger.debug(f"Failed to read {metadata_path}: {e}")
return None
-2
View File
@@ -1534,12 +1534,10 @@ class TestLoraManagerMediaServing(ImageRouteCoverageCase):
self.assertEqual(await self._status(self._link_image(self._example())), 200)
self.assertIsNotNone(lora_utils._layout_cache._entry)
stored = lora_utils._layout_cache._entry
with patch.object(IntegrationConfig, "LORA_MANAGER_PATH", str(self.sidecars)):
self.assertEqual(self.api._lora_image_dirs(), [])
# The warm entry for the real install was never handed out for it.
self.assertIsNone(lora_utils.cached_lora_manager_layout(str(self.sidecars))[0])
self.assertIsNotNone(stored)
async def test_serve_image_builds_the_allow_list_in_the_executor(self):
calls = self._spy_executor()
+1 -1
View File
@@ -15,8 +15,8 @@ import tempfile
import threading
import time
import unittest
from pathlib import Path, PureWindowsPath
from dataclasses import replace
from pathlib import Path, PureWindowsPath
from types import SimpleNamespace
from unittest.mock import patch
+8
View File
@@ -224,6 +224,14 @@ class TestReadLoraMetadata(unittest.TestCase):
result = read_lora_metadata(Path("/nonexistent/file.metadata.json"))
self.assertIsNone(result)
def test_returns_none_for_a_file_that_is_not_utf8(self):
# #362: one malformed sidecar is skipped; it must not fail the whole
# trigger-word load (now logged with a traceback) or the review.
with tempfile.TemporaryDirectory() as folder:
path = Path(folder) / "bad.metadata.json"
path.write_bytes(b'{"model_name": "\xff\xfe"}')
self.assertIsNone(read_lora_metadata(path))
class TestGetLoraImageCacheDir(unittest.TestCase):
"""Test get_lora_image_cache_dir — returns and creates cache path."""