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): passView on GitHub (pinned to f9235ebbf1)
Solutions
- Send both fields: {"msg_id": <int>, "content": "<new text>"}
- Check the client is not renaming keys — the exact names msg_id and content are required
- 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
- Pin the payload contract with a shared type/schema
- Disable the save button until msg_id is known and content is non-null
- Remember msg_id=0 and '' are rejected by truthiness, only content may be empty
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
- {key} must be an integer
- Password is required
- Document is not linked to a source PDF
- Message is required
- await res.text()
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/9b3e63e4bd3a7285.
Report an issue: GitHub.