[Bug]: JsonCache.get() crashes with unhandled AttributeError on non-dict or invalid envelope JSON payloads
Maintainer thường phản hồi trong vòng 5 ngày
Chưa có ai nhận issue này.
- #1 của @wangkangmao — đã đóng, không merge
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 82/100
Hướng nghiên cứu
Đọc packages/graphrag-cache/graphrag_cache/json_cache.py và so sánh JsonCache.get() với cách hoạt động của SQLiteCache được mô tả trong issue. Kiểm tra các bài kiểm tra cache và bổ sung phạm vi kiểm thử cho các giá trị JSON hợp lệ không phải là từ điển và các từ điển thiếu result. Công việc hoàn tất khi các mục không hợp lệ bị xóa và get() trả về None mà không phát sinh ngoại lệ.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Do you need to file an issue?
- I have searched the existing issues and this bug is not already filed.
- I believe this is a legitimate bug, not just a question. If this is a question, please use the Discussions area.
Describe the bug
In packages/graphrag-cache/graphrag_cache/json_cache.py, JsonCache.get() decodes stored cache data using json.loads(data) and assumes the deserialized object is always a dictionary:
async def get(self, key: str) -> Any:
"""Get method definition."""
if await self.has(key):
try:
data = await self._storage.get(key)
data = json.loads(data)
except UnicodeDecodeError:
await self._storage.delete(key)
return None
except json.decoder.JSONDecodeError:
await self._storage.delete(key)
return None
else:
return data.get("result")
If the storage contains a valid JSON payload that is not a dictionary (e.g. a JSON array [1, 2, 3], primitive string, number, or boolean from an external tool, corrupted state, or older schema format), json.loads() succeeds without raising JSONDecodeError. Then execution jumps to data.get("result"), immediately raising:
AttributeError: 'list' object has no attribute 'get'
Furthermore, unlike SQLiteCache (which explicitly handles invalid envelopes and purges corrupted entries via if not isinstance(data, dict) or "result" not in data:), JsonCache neither catches this exception nor deletes the offending key. As a result, every subsequent call to cache.get(key) repeatedly crashes the pipeline instead of recovering gracefully with None.
Steps to reproduce
Self-contained minimal reproduction (no external APIs or configs needed):
import asyncio
import json
class InMemoryStorage:
def __init__(self):
self._store = {}
async def get(self, key):
return self._store.get(key)
async def set(self, key, value):
self._store[key] = value
async def has(self, key):
return key in self._store
async def delete(self, key):
self._store.pop(key, None)
# Directly reproduces packages/graphrag-cache/graphrag_cache/json_cache.py
class JsonCache:
def __init__(self, storage):
self._storage = storage
async def get(self, key: str):
if await self.has(key):
try:
data = await self._storage.get(key)
data = json.loads(data)
except UnicodeDecodeError:
await self._storage.delete(key)
return None
except json.decoder.JSONDecodeError:
await self._storage.delete(key)
return None
else:
return data.get("result")
return None
async def has(self, key: str) -> bool:
return await self._storage.has(key)
async def main():
storage = InMemoryStorage()
cache = JsonCache(storage)
# Store a valid JSON array or primitive payload under a cache key
await storage.set("bad_envelope", "[1, 2, 3]")
# Crashes with unhandled AttributeError: 'list' object has no attribute 'get'
result = await cache.get("bad_envelope")
print("Result:", result)
asyncio.run(main())
Expected Behavior
Consistent with SQLiteCache, JsonCache.get() should verify that isinstance(data, dict) and "result" in data. If invalid, it should purge the corrupted key from storage and safely return None.
Proposed fix:
async def get(self, key: str) -> Any | None:
"""Get method definition."""
if await self.has(key):
try:
data = await self._storage.get(key)
data = json.loads(data)
except (UnicodeDecodeError, json.decoder.JSONDecodeError):
await self._storage.delete(key)
return None
else:
if not isinstance(data, dict) or "result" not in data:
await self._storage.delete(key)
return None
return data["result"]
return None
GraphRAG Config Used
N/A (Reproducible directly in graphrag_cache.json_cache.JsonCache)
Logs and screenshots
Traceback (most recent call last):
File "repro.py", line 47, in <module>
asyncio.run(main())
File ".../asyncio/runners.py", line 190, in run
return runner.run(main)
File ".../asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
File ".../asyncio/base_events.py", line 654, in run_until_complete
return future.result()
File "repro.py", line 43, in main
result = await cache.get("bad_envelope")
File "repro.py", line 32, in get
return data.get("result")
AttributeError: 'list' object has no attribute 'get'
Additional context
- GraphRAG Version:
mainbranch (post-monorepo split / PR #2591) - Python Version: Python 3.10 / 3.11 / 3.12
- Operating System: Linux / macOS / Windows
- Note: We have prepared a fix with regression tests and can submit a PR if this looks good to maintainers.
- Ngôn ngữ chính
- Python
- Star
- 36.6k
- Fork
- 3.9k
- Merge trung bình
- 4 ngày 11 giờ
- Pull request đã merge (30 ngày)
- 1
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của microsoft/graphrag
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
microsoft/graphrag#2626 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 5 ngày
-
[Bug]: response_format_json_object=True is silently dropped, so JSON mode never reaches the modelĐang mởbug triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
microsoft/graphrag#2625 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 5 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 95/100
Maintainer thường phản hồi trong vòng 5 ngày
-
[Bug]: JSONLinesFileReader drops rows containing U+2028, U+2029 or U+0085 (uses str.splitlines)Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
microsoft/graphrag#2594 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 5 ngày
-
[Bug]: TokenChunker never terminates when chunking overlap >= size (no validation of size/overlap)Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
microsoft/graphrag#2593 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 5 ngày
Tất cả issue của microsoft/graphrag
Issue tương tự
-
bug
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 78/100
splunk/security_content#4418 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug / Enhancement]: Improve teleop_robot CLI with configurable timeout, robust input validation, and clean ROS shutdownCó thể đã có người làm @muskan-creates352 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 3 ngày
-
bug(pipelines): shortcode stripping deletes text between a {{< >}} shortcode and the next {{% %}}Có thể đã có người làm @Ashborne-lab đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
kubeflow/docs-agent#293 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
Imbad0202/academic-research-skills#1093 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Input: placeholder drawn in the text colour when the empty Input is focused but not yet editedĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
pierreaubert/gpui-toolkit#114 ·
Maintainer thường phản hồi trong vòng 1 ngày