Billionmail/BillionMail · error
Failed to save chat
Error message
Failed to save chat
What it means
After mutating the loaded chat with the new supplier/model, Chat persists it with SaveChat and returns this error if saving fails, swallowing the underlying cause. It means the chat state could not be written, so the session is not activated.
Source
Thrown at core/internal/service/askai/chat.go:269
return errors.New("Supplier not found")
}
modelInfo := GetModelInfo(supplierName, modelId)
if modelInfo == nil {
return errors.New("Model not found")
}
// Check if the chat is already active
chatInfo, err := GetChat(chatId)
if err != nil {
return errors.New("Chat not found")
}
// set the chat information
chatInfo.SupplierName = supplierName
chatInfo.ModelId = modelId
err = SaveChat(chatId, chatInfo)
if err != nil {
return errors.New("Failed to save chat")
}
ChatStatus[chatId] = true // Set chat status to active
defer func() {
delete(ChatStatus, chatId) // Ensure chat status is removed after processing
}()
aiObj := NewOpenAI(ctx, supplierInfo.ApiKey, supplierInfo.BaseUrl, modelId, chatId, supplierName, modelInfo.MaxTokens)
if aiObj == nil {
return errors.New("failed to initialize AI client")
}
aiObj.GetClient()
return aiObj.Chat(content, isText)
}
// RemoveChat removes a chat by its ID
// This function should handle the logic for removing a chat based on the provided chat ID
func RemoveChat(chatId string) error {View on GitHub (pinned to fc36c76c05)
Solutions
- Check the persistence layer (Redis/store) used by SaveChat is healthy
- Inspect SaveChat to log/propagate its underlying error instead of masking it
- Retry Chat once the store is available; the chat status flag was not set, so state is consistent
Example fix
// before
if err := SaveChat(chatId, chatInfo); err != nil {
return errors.New("Failed to save chat")
}
// after
if err := SaveChat(chatId, chatInfo); err != nil {
return fmt.Errorf("failed to save chat %s: %w", chatId, err)
} Defensive patterns
Strategy: try-catch
Try / catch
if err := askai.Chat(ctx, chatId, supplier, model, content, true); err != nil {
if err.Error() == "Failed to save chat" {
// check store health (redis/db) then retry with backoff
return retryable(err)
}
return err
} Prevention
- Monitor the backing store used by SaveChat
- Improve the library to wrap the underlying save error with %w
- Avoid concurrent writes to the same chatId
When it happens
Trigger: Calling Chat when SaveChat fails internally — e.g., storage/Redis unavailable, serialization failure of chatInfo, or underlying store write error.
Common situations: Redis or backing store down during deployment; disk/memory pressure on the persistence layer; concurrent writes corrupting the chat record causing save rejection.
Related errors
- Chat not found
- Content cannot be empty
- Supplier not found
- Model not found
- failed to initialize AI client
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/ef0a05bbd0408b40.
Report an issue: GitHub.