LykosAI/StabilityMatrix · error · InvalidOperationException

No user message found to retry

Error message

No user message found to retry

What it means

RetryGenerationAsync loads all conversation messages and looks for the last message with Role == MessageRole.User, since a retry needs the original prompt to re-send. If the conversation contains no user message (empty conversation, or only assistant/system messages), it throws InvalidOperationException. This prevents retrying a conversation that has nothing to retry.

Solutions

  1. Check that the conversation has at least one user message before calling RetryGenerationAsync
  2. If the conversation is empty, send a new prompt via the normal generate path instead of retry
  3. Inspect persisted messages (GetMessagesAsync) and repair/re-seed the user message if it was lost
  4. Verify the retry targets the correct conversationId

Example fix

// before
await chatService.RetryGenerationAsync(conversationId, providerId);
// after
var messages = await chatService.GetMessagesAsync(conversationId);
if (!messages.Any(m => m.Role == MessageRole.User))
{
    throw new InvalidOperationException("Nothing to retry: no user message in this conversation.");
}
await chatService.RetryGenerationAsync(conversationId, providerId);
Defensive patterns

Strategy: validation

Validate before calling

var hasUserMessage = (await chatService.GetMessagesAsync(conversationId))
    .Any(m => m.Role == MessageRole.User);
if (!hasUserMessage) return; // nothing to retry

Type guard

bool IsRetryable(IReadOnlyList<ConversationMessage> msgs) =>
    msgs.Any(m => m.Role == MessageRole.User);

Try / catch

try { await chatService.RetryGenerationAsync(convId, providerId); }
catch (InvalidOperationException ex) when (ex.Message.Contains("No user message"))
{
    // disable retry UI / start a new prompt instead
}

Prevention

When it happens

Trigger: Calling RetryGenerationAsync on a conversation whose message list contains zero messages with Role User - e.g. a freshly created empty conversation, a conversation where generation failed before the user message was persisted, or a conversation containing only assistant/system messages.

Common situations: Retrying immediately after a failed first generation that never saved the user message; retrying a newly created conversation by mistake; test/debug conversations constructed programmatically without user turns.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of LykosAI/StabilityMatrix@af93d6ef57 (2026-09-12). Data as JSON: /api/errors/cb9deaada009953d. Report an issue: GitHub.

Appendix: source

Thrown at StabilityMatrix.Core/Services/ImageGeneration/ImageGenerationChatService.cs:856

                    carryForwardImagePath = GetMessageImagePaths(lastAssistantImage)
                        .FirstOrDefault(File.Exists);
                    if (carryForwardImagePath != null)
                    {
                        logger.LogInformation(
                            "Retry: Switching to thinking model with incompatible history. "
                                + "Carrying forward last image as input: {ImagePath}",
                            carryForwardImagePath
                        );
                    }
                }
            }
        }

        // Find the last user message
        var lastUserMessage = allMessages.LastOrDefault(m => m.Role == MessageRole.User);
        if (lastUserMessage == null)
        {
            throw new InvalidOperationException("No user message found to retry");
        }

        // Build conversation history (everything except the last user message)
        // If we're carrying forward an image, skip the incompatible history
        var conversationHistory = new List<ConversationMessage>();

        if (string.IsNullOrEmpty(carryForwardImagePath))
        {
            foreach (var m in allMessages.Where(msg => msg.Id != lastUserMessage.Id))
            {
                var messageImagePaths = GetMessageImagePaths(m).Where(File.Exists).ToList();

                if (messageImagePaths.Count == 0)
                {
                    conversationHistory.Add(
                        new ConversationMessage
                        {
                            Role = m.Role,

View on GitHub (pinned to af93d6ef57)