{"record":{"id":"e37247289f2ef9a4","repo":"odysseus-dev/odysseus","slug":"empty-memory","errorCode":null,"errorMessage":"empty memory","messagePattern":"empty memory","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"routes/memory/memory_routes.py","lineNumber":120,"sourceCode":"        request: Request,\n        memory_data: Optional[MemoryAddRequest] = None\n    ):\n        \"\"\"Add a new memory entry with optional category, source, and session reference.\"\"\"\n        from src.auth_helpers import require_privilege\n        require_privilege(request, \"can_manage_memory\")\n        if memory_data is None:\n            form = await request.form()\n            memory_data = MemoryAddRequest(\n                text=form.get(\"text\"),\n                category=form.get(\"category\", \"fact\"),\n                source=form.get(\"source\", \"user\"),\n                session_id=form.get(\"session_id\")\n            )\n\n        user = _owner(request)\n        text = (memory_data.text or \"\").strip()\n        if not text:\n            raise HTTPException(400, \"empty memory\")\n        user_mem = memory_manager.load(owner=user)\n        if memory_manager.find_duplicates(text, user_mem):\n            return {\"ok\": True, \"count\": len(user_mem), \"message\": \"Memory already exists\"}\n\n        if memory_data.session_id:\n            try:\n                session_obj = session_manager.get_session(memory_data.session_id)\n            except KeyError:\n                raise HTTPException(404, \"Session not found\")\n            _assert_session_owner(session_obj, user)\n\n        new_entry = memory_manager.add_entry(text, memory_data.source, memory_data.category, owner=user)\n        if memory_data.session_id:\n            new_entry[\"session_id\"] = memory_data.session_id\n        all_mem = _load_for_update(memory_manager)\n        all_mem.append(new_entry)\n        memory_manager.save(all_mem)\n        # Sync vector index","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/memory/memory_routes.py#L102-L138","documentation":"On POST /api/memory/add, the request's text field is stripped and, if empty, rejected with 400 'empty memory' before load/duplicate-check/add run. The endpoint accepts either a typed MemoryAddRequest body or falls back to reading Form fields (text, category, source, session_id), so whitespace-only or missing text in either shape triggers it.","triggerScenarios":"Posting form data with text=\"\" or \"   \"; sending text as null in the JSON model; form-binding bug where the text input name is wrong (e.g. 'content' instead of 'text') so the field arrives empty.","commonSituations":"Frontend submitting before the textarea is filled; client field-name mismatch; automated memory writers emitting empty strings on parse failures.","solutions":["Validate client-side that text.strip() is non-empty before posting.","Use the exact field name 'text' (Form fallback) or a well-formed MemoryAddRequest body.","If the source produced nothing (empty transcript/extraction), skip the memory-add call entirely."],"exampleFix":"# before\nrequests.post(f\"{base}/api/memory/add\", data={\"text\": memo or \"\"})\n\n# after\nif memo and memo.strip():\n    requests.post(f\"{base}/api/memory/add\", data={\"text\": memo.strip()})","handlingStrategy":"validation","validationCode":"def memory_text_ok(text) -> bool:\n    return isinstance(text, str) and bool(text.strip())","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Strip and check text client-side before posting.","Use the exact field name 'text'.","Skip the add call entirely when the upstream source produced no content."],"tags":["memory","validation","form-data","empty-input"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}