OtterMind/Chat2DB · error · BusinessException

ai.chat.history.loadMessagesFailed

ai.chat.history.loadMessagesFailed

Error message

ai.chat.history.loadMessagesFailed

What it means

Thrown by AiChatHistoryServiceImpl.loadMessages in the catch(Exception) around objectMapper.readValue of <sessionId>.json. Args are {path, e.getMessage()}. Mirrors the sessions load failure but for a single session's message list; any JSON/IO exception aborts message loading for that session.

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

            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);
        try {
            Files.createDirectories(path.getParent());
            MessagesFile file = new MessagesFile();
            file.setMessages(messages);
            objectMapper.writerWithDefaultPrettyPrinter().writeValue(path.toFile(), file);
        } catch (IOException e) {
            throw new BusinessException("ai.chat.history.persistMessagesFailed", new Object[]{path, e.getMessage()}, e);
        }
    }

    private void touchSession(Long userId, String sessionId) {
        List<AiChatSession> sessions = loadSessions(userId);
        sessions.stream()

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Back up and remove the corrupt <sessionId>.json so the session starts with an empty message history.
  2. Make persistMessages atomic (temp file + ATOMIC_MOVE) to prevent half-written files on crash.
  3. Add @JsonIgnoreProperties(ignoreUnknown=true) to AiChatMessage for forward-compatible deserialization after upgrades.

Example fix

// before: non-atomic message write
objectMapper.writerWithDefaultPrettyPrinter().writeValue(path.toFile(), file);

// after: atomic temp+move
Path tmp = path.resolveSibling(path.getFileName() + ".tmp");
objectMapper.writerWithDefaultPrettyPrinter().writeValue(tmp.toFile(), file);
Files.move(tmp, path, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
Defensive patterns

Strategy: try-catch

Try / catch

try {
    history.listMessages(sessionId);
} catch (BusinessException e) {
    if ("ai.chat.history.loadMessagesFailed".equals(e.getCode())) {
        Path p = (Path) e.getArgs()[0];
        backupAndQuarantine(p);
        return List.of(); // empty history for this session
    }
    throw e;
}

Prevention

When it happens

Trigger: The file <basePath>/ai-chat-history/<sessionId>.json exists but is corrupt or unreadable: truncated JSON from a crashed persistMessages, schema drift after an upgrade, or an IOException reading the file. Unlike sessions, a missing messages file is tolerated (returns empty list) - only an existing-but-unreadable file throws.

Common situations: Process killed mid-write of messages leaving a half file; manual edit; Jackson cannot bind AiChatMessage after a field change; storage corruption.

Related errors


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