OtterMind/Chat2DB · error · BusinessException

ai.chat.history.persistSessionsFailed

ai.chat.history.persistSessionsFailed

Error message

ai.chat.history.persistSessionsFailed

What it means

Thrown by AiChatHistoryServiceImpl.persistSessions in the catch(IOException) while writing sessions-<userId>.json (creating parent dirs or serializing). Args are {path, e.getMessage()}. Any write failure aborts the persistence of the user's session list.

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:215

            return new ArrayList<>();
        }
        try {
            SessionsFile file = objectMapper.readValue(path.toFile(), SessionsFile.class);
            return file.getSessions() != null ? file.getSessions() : new ArrayList<>();
        } catch (Exception e) {
            throw new BusinessException("ai.chat.history.loadSessionsFailed", new Object[]{path, e.getMessage()}, e);
        }
    }

    private void persistSessions(Long userId, List<AiChatSession> sessions) {
        Path path = sessionsPath(userId);
        try {
            Files.createDirectories(path.getParent());
            SessionsFile file = new SessionsFile();
            file.setSessions(sessions);
            objectMapper.writerWithDefaultPrettyPrinter().writeValue(path.toFile(), file);
        } catch (IOException e) {
            throw new BusinessException("ai.chat.history.persistSessionsFailed", new Object[]{path, e.getMessage()}, e);
        }
    }

    private List<AiChatMessage> loadMessages(String sessionId) {
        Path path = messagesPath(sessionId);
        if (!Files.exists(path)) {
            return new ArrayList<>();
        }
        try {
            MessagesFile file = objectMapper.readValue(path.toFile(), MessagesFile.class);
            return file.getMessages() != null ? file.getMessages() : new ArrayList<>();
        } catch (Exception e) {
            throw new BusinessException("ai.chat.history.loadMessagesFailed", new Object[]{path, e.getMessage()}, e);
        }
    }

    private void persistMessages(String sessionId, List<AiChatMessage> messages) {
        Path path = messagesPath(sessionId);

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Verify the process user has read+write+execute on ConfigUtils.getBasePath()/ai-chat-history and that the volume has free space/inodes.
  2. If read-only, set chat2db.base.path (or the equivalent) to a writable location.
  3. Free disk space if the volume is full; the operation is retried on the next session mutation.
  4. Ensure no regular file occupies the ai-chat-history directory name.

Example fix

// before: persisting to a read-only/full volume
objectMapper.writerWithDefaultPrettyPrinter().writeValue(path.toFile(), file);

// after: confirm writability and report a clear error
Files.createDirectories(path.getParent());
if (!Files.isWritable(path.getParent())) {
    throw new IllegalStateException("ai-chat-history dir not writable: " + path.getParent());
}
objectMapper.writerWithDefaultPrettyPrinter().writeValue(path.toFile(), file);
Defensive patterns

Strategy: validation

Validate before calling

Path dir = Paths.get(ConfigUtils.getBasePath(), "ai-chat-history");
Files.createDirectories(dir);
if (!Files.isWritable(dir)) {
    throw new IllegalStateException("not writable: " + dir);
}

Try / catch

try {
    history.createSession(...);
} catch (BusinessException e) {
    if ("ai.chat.history.persistSessionsFailed".equals(e.getCode())) {
        return ResponseEntity.status(507).body("storage full or read-only");
    }
    throw e;
}

Prevention

When it happens

Trigger: Files.createDirectories(path.getParent()) fails (permission denied, read-only mount), or the Jackson writeValue fails: disk full, quota exceeded, the path is on a read-only filesystem, or the directory was removed under the process.

Common situations: Disk full or inode exhaustion in the chat2db data dir; the process user lacks write permission on <basePath>/ai-chat-history/; a read-only container volume; a parent path collision with a regular file.

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/026633423e115d59. Report an issue: GitHub.