odysseus-dev/odysseus · warning · HTTPException

msg_id and content are required

Error message

msg_id and content are required

What it means

Validation failure in POST /api/session/{session_id}/edit-message: the JSON body must contain both msg_id and content. The guard `if not msg_id or content is None` rejects missing/null msg_id, and also any falsy msg_id (0, empty string), while content only has to be non-None (empty string is allowed).

Source

Thrown at routes/history/history_routes.py:351

                return {"status": "ok", "deleted": deleted}
            finally:
                db.close()
        except KeyError:
            raise HTTPException(404, "Session not found")
        except Exception as e:
            logger.error(f"Delete messages error {session_id}: {e}")
            raise HTTPException(500, str(e))

    @router.post("/api/session/{session_id}/edit-message")
    async def edit_message(request: Request, session_id: str):
        """Edit the content of a message by its database ID."""
        _verify_session_owner(request, session_id)
        try:
            body = await request.json()
            msg_id = body.get("msg_id")
            content = body.get("content")
            if not msg_id or content is None:
                raise HTTPException(400, "msg_id and content are required")

            _reserve_message_uploads(request, content)

            session = session_manager.get_session(session_id)
            db = SessionLocal()
            try:
                db_msg = db.query(DbChatMessage).filter(
                    DbChatMessage.id == msg_id,
                    DbChatMessage.session_id == session_id,
                ).first()
                if not db_msg:
                    raise HTTPException(404, "Message not found")

                db_msg.content = content
                meta = {}
                if db_msg.meta_data:
                    try: meta = json.loads(db_msg.meta_data)
                    except (json.JSONDecodeError, ValueError): pass

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Send both fields: {"msg_id": <int>, "content": "<new text>"}
  2. Check the client is not renaming keys — the exact names msg_id and content are required
  3. Do not send the request at all when the edit box is empty-and-submitted; guard client-side for msg_id being truthy and content being non-null

Example fix

// before
await fetch(`/api/session/${sid}/edit-message`, {
  method: 'POST',
  body: JSON.stringify({ id: msgId, content })
});
// after
if (!msgId || content === null || content === undefined) return;
await fetch(`/api/session/${sid}/edit-message`, {
  method: 'POST',
  body: JSON.stringify({ msg_id: msgId, content })
});
Defensive patterns

Strategy: validation

Validate before calling

function validEditPayload(b) { return Number.isInteger(b.msg_id) && b.msg_id > 0 && 'content' in b && b.content !== null && b.content !== undefined; }

Type guard

const isEditBody = (b) => !!b && typeof b === 'object' && 'msg_id' in b && 'content' in b && b.content !== null;

Prevention

When it happens

Trigger: POSTing {} or {"msg_id": 5} or {"content": "hi"} to the edit-message endpoint; sending msg_id as an empty string; a frontend bug that sends the field under a different key (e.g. "id" instead of "msg_id").

Common situations: Frontend/backend contract drift after renaming the payload key; sending a DB id of 0 (rejected even though technically an id); sending content: null when the user cleared the input box.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/9b3e63e4bd3a7285. Report an issue: GitHub.