wavetermdev/waveterm · error

expected StoredChatMessage, got %T

Error message

expected StoredChatMessage, got %T

What it means

RunChatStep converts the stored chat's NativeMessages, asserting each is a *StoredChatMessage; any other concrete type fails this assertion with the actual type reported. The openaichat backend only understands its own stored message wrapper.

Source

Thrown at pkg/aiusechat/openaichat/openaichat-backend.go:54

	chat := chatstore.DefaultChatStore.Get(chatOpts.ChatId)
	if chat == nil {
		return nil, nil, nil, fmt.Errorf("chat not found: %s", chatOpts.ChatId)
	}

	if chatOpts.Config.TimeoutMs > 0 {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, time.Duration(chatOpts.Config.TimeoutMs)*time.Millisecond)
		defer cancel()
	}

	// Convert stored messages to chat completions format
	var messages []ChatRequestMessage

	// Convert native messages
	for _, genMsg := range chat.NativeMessages {
		chatMsg, ok := genMsg.(*StoredChatMessage)
		if !ok {
			return nil, nil, nil, fmt.Errorf("expected StoredChatMessage, got %T", genMsg)
		}
		messages = append(messages, *chatMsg.Message.clean())
	}

	req, err := buildChatHTTPRequest(ctx, messages, chatOpts)
	if err != nil {
		return nil, nil, nil, err
	}

	client, err := aiutil.MakeHTTPClient(chatOpts.Config.ProxyURL)
	if err != nil {
		return nil, nil, nil, err
	}
	resp, err := client.Do(req)
	if err != nil {
		return nil, nil, nil, fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()

View on GitHub (pinned to a4447c1563)

Solutions

  1. Ensure only messages created by the openaichat backend are added to this chat's NativeMessages
  2. Convert or re-create foreign messages as StoredChatMessage before running the step
  3. Check the chat-loading code isn't deserializing into the wrong message type

Example fix

// before
chat.NativeMessages = append(chat.NativeMessages, openaiMsg) // wrong type
// after
chat.NativeMessages = append(chat.NativeMessages, &StoredChatMessage{Message: toStored(openaiMsg)})
Defensive patterns

Strategy: type-guard

Validate before calling

for i, m := range chat.NativeMessages {
    if _, ok := m.(*StoredChatMessage); !ok {
        return fmt.Errorf("native message %d is %T, not StoredChatMessage", i, m)
    }
}

Type guard

func isStoredChatMessage(m any) bool { _, ok := m.(*StoredChatMessage); return ok }

Prevention

When it happens

Trigger: chat.NativeMessages contains native messages produced by another backend (e.g. *OpenAIChatMessage from the openai responses backend) instead of *StoredChatMessage.

Common situations: Persisting/loading chats across backends; mixing backends in one chat history; upgrading the library where message representations changed.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/750d6868a2aeb094. Report an issue: GitHub.