From e29c523c12c009f97aa25509eab3599d6920bbbc Mon Sep 17 00:00:00 2001 From: disqualifier Date: Sun, 28 Jun 2026 17:18:28 -0400 Subject: [PATCH] fix: _load raises on valid-but-non-object JSON a store file holding valid JSON that is not an object (null/number/string/array) returned a non-dict, breaking get/set/delete/get_all. now raises ValueError, matching the documented corrupt-file contract. Signed-off-by: disqualifier --- src/aiokv/aiokv.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/aiokv/aiokv.py b/src/aiokv/aiokv.py index b61f5ab..522f463 100644 --- a/src/aiokv/aiokv.py +++ b/src/aiokv/aiokv.py @@ -100,14 +100,21 @@ class AioKV: async def _load(self) -> Dict[str, Any]: """load the store from disk, returning {} if the file is absent or empty - a truncated/corrupt file raises JSONDecodeError — surfaced to the caller - rather than silently masking a real corruption. + a truncated/corrupt file raises JSONDecodeError, and a file holding valid + JSON that is not an object (e.g. a bare list, number, or null) raises + ValueError — both surfaced to the caller rather than silently masking a + real corruption or returning a non-dict that breaks every other method. """ if not await asyncio.to_thread(os.path.exists, self.file): return {} async with aiofiles.open(self.file, mode="r") as f: data = await f.read() - return json.loads(data) if data else {} + if not data: + return {} + loaded = json.loads(data) + if not isinstance(loaded, dict): + raise ValueError(f"store file {self.file} does not hold a JSON object") + return loaded async def _save(self, cache: Dict[str, Any]) -> None: """write the store atomically: temp file in the same dir, then os.replace