OtterMind/Chat2DB · critical · IllegalStateException
Failed to load ai config from
Error message
Failed to load ai config from
What it means
Thrown as IllegalStateException('Failed to load ai config from ' + storagePath) by AiModelConfigServiceImpl.loadFromDisk in the catch(Exception) when reading the persisted AI config JSON fails. This runs at construction/startup, so a corrupt config store can block the AI subsystem from initializing. The wrapped exception carries the root cause (parse error or IOException).
Source
Thrown at chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ai/AiModelConfigServiceImpl.java:392
private synchronized void loadFromDisk() {
if (!Files.exists(storagePath)) {
return;
}
try {
StorageData data = objectMapper.readValue(storagePath.toFile(), StorageData.class);
Map<Long, List<AiModelConfig>> loadedConfigMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(data.getConfigs())) {
data.getConfigs().forEach(config -> {
config.setApiKey(decryptApiKey(config.getApiKey()));
Long userId = defaultValue(config.getUserId(), 0L);
loadedConfigMap.computeIfAbsent(userId, key -> new ArrayList<>()).add(config);
});
}
userConfigMap.clear();
userConfigMap.putAll(loadedConfigMap);
} catch (Exception e) {
throw new IllegalStateException("Failed to load ai config from " + storagePath, e);
}
}
private synchronized void persistToDisk() {
try {
Files.createDirectories(storagePath.getParent());
StorageData data = new StorageData();
List<AiModelConfig> all = userConfigMap.values().stream()
.flatMap(List::stream)
.map(this::encryptedCopy)
.collect(Collectors.toList());
data.setConfigs(all);
objectMapper.writerWithDefaultPrettyPrinter().writeValue(storagePath.toFile(), data);
} catch (IOException e) {
throw new IllegalStateException("Failed to persist ai config to " + storagePath, e);
}
}
View on GitHub (pinned to 5ee1e990e7)
Solutions
- Back up and remove the corrupt config store file so loadFromDisk starts empty (configs are then re-saved on next save).
- Make persistToDisk atomic (write temp then ATOMIC_MOVE) to prevent half-written stores on crash.
- Add @JsonIgnoreProperties(ignoreUnknown=true) to StorageData/AiModelConfig for forward-compatible deserialization across upgrades.
- Inspect the wrapped exception cause to distinguish JSON corruption from an IO error.
Example fix
// before: direct write, corruptible on crash
objectMapper.writerWithDefaultPrettyPrinter().writeValue(storagePath.toFile(), data);
// after: atomic + tolerant
objectMapper.writerWithDefaultPrettyPrinter().writeValue(tmp.toFile(), data);
Files.move(tmp, storagePath, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
// and on the DTOs:
@JsonIgnoreProperties(ignoreUnknown = true)
public class StorageData { ... } Defensive patterns
Strategy: try-catch
Try / catch
try {
aiConfigService = /* load */;
} catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Failed to load ai config from")) {
Path store = extractPathFrom(e); // parse storagePath from message
backupAndQuarantine(store); // move aside the corrupt store
aiConfigService = /* retry load with empty store */;
} else throw e;
} Prevention
- Make persistToDisk atomic (temp + ATOMIC_MOVE) to prevent corrupt stores on crash.
- Add @JsonIgnoreProperties(ignoreUnknown=true) to StorageData/AiModelConfig for upgrade safety.
- Back up the corrupt config store before discarding it; inspect the wrapped cause.
When it happens
Trigger: The ai config storage file (storagePath, the persisted model-config store) exists but objectMapper.readValue cannot deserialize it: truncated/corrupt JSON from a crashed persistToDisk, a schema change to StorageData/AiModelConfig the stored file does not match, or an IOException reading the file.
Common situations: Process was killed during persistToDisk leaving a half-written config file; the file was manually edited; an upgrade changed AiModelConfig fields (e.g. a new required field) so stored configs no longer bind; the config store is on a failing/unmounted volume.
Related errors
- ai.chat.history.loadSessionsFailed
- ai.chat.history.loadMessagesFailed
- ai.model.config.required
- ai.model.config.notFound
- provider is required
AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14).
Data as JSON: /api/errors/5664d89dfede619d.
Report an issue: GitHub.