Skip to content

[Bug] clean_json_response crashes with cryptic AttributeError when given None #1525

@Ptah-CT

Description

@Ptah-CT

Summary

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.

Proposed fix

if response is None:
    raise ValueError(
        "clean_json_response received None — upstream LLM call likely "
        "failed silently (check timed_with_status / generate() error handling)."
    )
return response.replace("```json", "").replace("```", "").strip()

PR follows.

Metadata

Metadata

Assignees

Labels

ai-doneAI task completed successfullybugSomething isn't working | 功能异常memosCore MemOS logic (memory, MCP, scheduler, API, database) | 核心模块

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions