OtterMind/Chat2DB · error · BusinessException

ai.chat.history.deleteMessagesFailed

ai.chat.history.deleteMessagesFailed

Error message

ai.chat.history.deleteMessagesFailed

What it means

Thrown by AiChatHistoryServiceImpl when Files.deleteIfExists(msgFile) raises IOException while deleting a session's messages JSON file. Args are {msgFile, e.getMessage()}. It only attempts deletion after the session was confirmed owned and removed from the sessions list. The i18n key is defined; resolves to the raw code if absent.

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

        }
        return all.subList(all.size() - maxMessages, all.size());
    }

    private synchronized void deleteSessionLocal(String sessionId, Long userId) {
        List<AiChatSession> sessions = loadSessions(userId);
        // Only delete the message file when the session was actually owned by
        // this user; otherwise a caller could delete another user's file by id.
        boolean removed = sessions.removeIf(s -> Objects.equals(s.getId(), sessionId));
        persistSessions(userId, sessions);
        if (!removed) {
            return;
        }

        Path msgFile = messagesPath(sessionId);
        try {
            Files.deleteIfExists(msgFile);
        } catch (IOException e) {
            throw new BusinessException("ai.chat.history.deleteMessagesFailed", new Object[]{msgFile, e.getMessage()}, e);
        }
    }

    private Path sessionsPath(Long userId) {
        return baseDir.resolve("sessions-" + userId + ".json");
    }

    private Path messagesPath(String sessionId) {
        return baseDir.resolve(sessionId + ".json");
    }

    private List<AiChatSession> loadSessions(Long userId) {
        Path path = sessionsPath(userId);
        if (!Files.exists(path)) {
            return new ArrayList<>();
        }
        try {
            SessionsFile file = objectMapper.readValue(path.toFile(), SessionsFile.class);

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Check filesystem permissions on <basePath>/ai-chat-history/ (ConfigUtils.getBasePath()/ai-chat-history) and ensure the process user owns it.
  2. Retry once after a short delay if a transient lock is likely (Windows AV), since deleteIfExists is idempotent.
  3. On a read-only volume, remount rw or relocate chat2db.base.path to a writable directory.
  4. Note the sessions list is already persisted without the session; orphaned <sessionId>.json can be swept on startup.

Example fix

// before: single attempt throws on transient lock
Files.deleteIfExists(msgFile);

// after: tolerate transient lock then mark for sweep
try {
    Files.deleteIfExists(msgFile);
} catch (IOException e) {
    orphanSweeper.mark(msgFile); // clean on next startup
    log.warn("could not delete {} now, scheduled for sweep", msgFile);
}
Defensive patterns

Strategy: try-catch

Validate before calling

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

Try / catch

try {
    history.deleteSession(userId, sessionId);
} catch (BusinessException e) {
    if ("ai.chat.history.deleteMessagesFailed".equals(e.getCode())) {
        // session already removed from list; orphan file can be swept later
        orphanSweeper.mark((Path) e.getArgs()[0]);
    }
}

Prevention

When it happens

Trigger: Deleting a session whose <sessionId>.json message file cannot be removed: permission denied on the file, the file is locked by another process (antivirus/indexer on Windows), or the filesystem is read-only. The sessions list is already updated, so the session disappears but its message file lingers.

Common situations: Running on a read-only or permission-restricted storage mount; an antivirus holding a lock on Windows; the ai-chat-history dir has wrong ownership; container volume mounted read-only.

Related errors


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