OtterMind/Chat2DB · error · BusinessException
ai.chat.history.sessionNotOwned
ai.chat.history.sessionNotOwned
Error message
ai.chat.history.sessionNotOwned
What it means
Thrown by AiChatHistoryServiceImpl.addMessageLocal when ownsSession(userId, sessionId) returns false, i.e. the given sessionId is not present in the current user's sessions file. Arg is {sessionId}. This is an authorization/ownership guard preventing a user from writing messages into another user's chat session. The i18n key is defined but resolves to the raw code if no message is present.
Source
Thrown at chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ai/AiChatHistoryServiceImpl.java:121
private synchronized AiChatSession createSessionLocal(Long userId, String title) {
AiChatSession session = new AiChatSession();
session.setId(UUID.randomUUID().toString());
session.setUserId(userId);
session.setTitle(title);
session.setGmtCreate(LocalDateTime.now());
session.setGmtModified(LocalDateTime.now());
List<AiChatSession> sessions = loadSessions(userId);
sessions.add(0, session);
persistSessions(userId, sessions);
return session;
}
private synchronized AiChatMessage addMessageLocal(String sessionId, Long userId, String role, String content,
String reasoningContent,
List<ChatAttachment> attachments) {
if (!ownsSession(userId, sessionId)) {
throw new BusinessException("ai.chat.history.sessionNotOwned", new Object[]{sessionId});
}
AiChatMessage message = new AiChatMessage();
message.setId(UUID.randomUUID().toString());
message.setSessionId(sessionId);
message.setRole(role);
message.setContent(content);
message.setReasoningContent(reasoningContent);
if (attachments != null) {
message.setAttachments(new ArrayList<>(attachments));
}
message.setGmtCreate(LocalDateTime.now());
List<AiChatMessage> messages = loadMessages(sessionId);
messages.add(message);
persistMessages(sessionId, messages);
touchSession(userId, sessionId);
return message;
}View on GitHub (pinned to 5ee1e990e7)
Solutions
- Re-fetch the session list for the current user before sending a message, and drop the stale sessionId from frontend state.
- If the session was deleted, create a new session via createSession first and use the returned sessionId.
- Catch BusinessException and surface a 'session not found' prompt offering to start a new chat.
Example fix
// before: reuse stale sessionId after delete
history.addMessage(deletedSessionId, userId, role, content);
// after: validate ownership client-side, recreate if missing
if (!sessionList.some(s => s.id === sessionId)) {
const fresh = await createSession();
sessionId = fresh.id;
}
history.addMessage(sessionId, userId, role, content); Defensive patterns
Strategy: validation
Validate before calling
// client-side: ensure sessionId is in the current user's session list
if (!sessions.some(s => s.id === sessionId)) {
sessionId = (await createSession()).id;
}
await history.addMessage(sessionId, role, content); Try / catch
try {
history.addMessage(sessionId, userId, role, content);
} catch (BusinessException e) {
if ("ai.chat.history.sessionNotOwned".equals(e.getCode())) {
// offer to start a new chat
return ResponseEntity.status(403).body("session not found");
}
throw e;
} Prevention
- Re-fetch the session list before sending after a delete or long idle.
- Clear stale sessionIds from frontend state on session deletion.
- Do not pass sessionIds from URLs or other users.
When it happens
Trigger: Calling addMessage with a sessionId that does not belong to the current identityService user: a fabricated/guessed sessionId, a sessionId from another user, a sessionId that was deleted, or a stale sessionId held in the frontend after the session was removed.
Common situations: Frontend keeps a sessionId in state after the user deleted that session; a shared/edited URL carries an old sessionId; concurrent tabs where one deleted the session; an attempt to inject another user's sessionId. Note the in-memory sessions list is re-read per call from sessions-<userId>.json, so deletion is reflected immediately.
Related errors
- The baseURL is not valid!
- The baseURL is not valid!
- Missing file
- ai.attachment.filePathRequired
- ai.chat.history.deleteMessagesFailed
AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14).
Data as JSON: /api/errors/f5899fb0af146e6f.
Report an issue: GitHub.