You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug] clean_json_response crashes with cryptic AttributeError when given None #1525
clean_json_response(response) in src/memos/mem_os/utils/format_utils.py:1393 calls response.replace(...) unconditionally. When response is None it dies with:
AttributeError: 'NoneType' object has no attribute 'replace'
The traceback points to format_utils.py:1403 and gives no hint about the real problem (an upstream LLM call returning None).
How None reaches here
In the codebase today this is reachable via the suggestion endpoint:
POST /product/suggestions
→ suggestion_handler.handle_get_suggestion_queries
→ llm.generate(message_list) # OpenAILLM.generate, decorated with @timed_with_status
→ (LLM call raises BadRequestError)
→ timed_with_status catches, no fallback configured, falls through to implicit `return None`
→ clean_json_response(None)
→ AttributeError ← user sees this
The deeper bug is in timed_with_status (filed separately as #1523). Even after that is fixed, however, defending against None here is cheap and turns the worst possible diagnostic experience (a wrong-line AttributeError) into a clear message that names the actual root cause.
Successfully addressed issue #1525 where clean_json_response() crashed with a cryptic AttributeError: 'NoneType' object has no attribute 'replace' when receiving None input from failed LLM calls.
Implementation Details
The fix was already present in the codebase at src/memos/mem_os/utils/format_utils.py:1410-1416. The implementation adds a defensive None check at function entry that raises a clear ValueError with a diagnostic message pointing to the root cause (upstream LLM call failures in timed_with_status decorator or generate() method).
Key Changes:
Added None check before calling .replace() method
Raises ValueError with message: "clean_json_response received None — upstream LLM call likely failed silently (check timed_with_status / generate() error handling)."
Updated docstring with Raises section documenting the ValueError
Preserves original behavior for all valid string inputs
Test Coverage
Added comprehensive test suite in tests/mem_os/test_format_utils.py with 8 test cases covering:
None input validation - Verifies ValueError is raised with diagnostic message
Markdown removal - Tests json and marker removal
Whitespace handling - Verifies leading/trailing whitespace is stripped
Plain JSON passthrough - Ensures valid JSON is unchanged
The fix improves debuggability by transforming an unhelpful error message into a clear diagnostic that immediately points developers to the upstream LLM call failure.
Activity
Memtensor-AI commentedon Jun 4, 2026
🤖 AutoDev has picked up this issue and started working on it.
Task ID:
db3666091a1dfa82Working branch:
bugfix/autodev-1525Target branch:
dev-20260604-v2.0.19Workflow: opsp (analysis → coding → testing → PR)
I will post the PR link here once done. If I need more information, I will ask in the comments.
test: add comprehensive tests for clean_json_response (issue #1525)
Memtensor-AI commentedon Jun 4, 2026
✅ AutoDev task
db3666091a1dfa82completed.Summary: ## Fix Summary
Successfully addressed issue #1525 where
clean_json_response()crashed with a crypticAttributeError: 'NoneType' object has no attribute 'replace'when receiving None input from failed LLM calls.Implementation Details
The fix was already present in the codebase at
src/memos/mem_os/utils/format_utils.py:1410-1416. The implementation adds a defensive None check at function entry that raises a clearValueErrorwith a diagnostic message pointing to the root cause (upstream LLM call failures intimed_with_statusdecorator orgenerate()method).Key Changes:
.replace()methodValueErrorwith message: "clean_json_response received None — upstream LLM call likely failed silently (check timed_with_status / generate() error handling)."Test Coverage
Added comprehensive test suite in
tests/mem_os/test_format_utils.pywith 8 test cases covering:json andmarker removalVerification
The fix has been verified through:
suggestion_handler.pywhere LLM calls can return NoneCommit Details
The fix improves debuggability by transforming an unhelpful error message into a clear diagnostic that immediately points developers to the upstream LLM call failure.
Base branch:
dev-20260604-v2.0.19Branch:
bugfix/autodev-1525Commit:
7291222PR: #1884
Assigned to: @MatthewZhuang, @CarltonXiang, @syzsunshine219
Reviewers: @MatthewZhuang, @CarltonXiang, @syzsunshine219
Fix #1525: [Bug] clean_json_response crashes with cryptic AttributeEr…
Dev 20260604 v2.0.19 (#2033)
Fix #1523: [Bug] timed_with_status decorator silently swallows except…
feat: chunk batch reflection scoring (#1957)
fix: remove 500-row cap that truncated viewer count displays (#1954)
feat: chunk batch reflection scoring (MemTensor#1957)
feat: chunk batch reflection scoring (MemTensor#1957)
feat: chunk batch reflection scoring (MemTensor#1957)
release: merge dev-v2.0.25 into main (#2156)
Dev 20260604 v2.0.19 (MemTensor#2033)
feat: chunk batch reflection scoring (MemTensor#1957)
release: merge dev-v2.0.25 into main (MemTensor#2156)