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

  1. Check the persistence layer (Redis/store) used by SaveChat is healthy
  2. Inspect SaveChat to log/propagate its underlying error instead of masking it
  3. 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

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


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/ef0a05bbd0408b40. Report an issue: GitHub.