{"record":{"id":"15d9645b77db6d7c","repo":"wavetermdev/waveterm","slug":"apitype-must-be-s-got-s","errorCode":null,"errorMessage":"APIType must be '%s', got '%s'","messagePattern":"APIType must be '(.+?)', got '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/anthropic/anthropic-convertmessage.go","lineNumber":817,"sourceCode":"\t\tcontentBlocks = append(contentBlocks, anthropicMessageContentBlock{\n\t\t\tType:      \"tool_result\",\n\t\t\tToolUseID: result.ToolUseID,\n\t\t\tContent:   content,\n\t\t\tIsError:   isError,\n\t\t})\n\t}\n\n\treturn &anthropicChatMessage{\n\t\tMessageId: uuid.New().String(),\n\t\tRole:      \"user\",\n\t\tContent:   contentBlocks,\n\t}, nil\n}\n\n// ConvertAIChatToUIChat converts an AIChat to a UIChat for Anthropic\nfunc ConvertAIChatToUIChat(aiChat uctypes.AIChat) (*uctypes.UIChat, error) {\n\tif aiChat.APIType != uctypes.APIType_AnthropicMessages {\n\t\treturn nil, fmt.Errorf(\"APIType must be '%s', got '%s'\", uctypes.APIType_AnthropicMessages, aiChat.APIType)\n\t}\n\n\tuiMessages := make([]uctypes.UIMessage, 0, len(aiChat.NativeMessages))\n\n\tfor i, nativeMsg := range aiChat.NativeMessages {\n\t\tanthropicMsg, ok := nativeMsg.(*anthropicChatMessage)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"message %d: expected *anthropicChatMessage, got %T\", i, nativeMsg)\n\t\t}\n\n\t\tuiMsg := anthropicMsg.ConvertToUIMessage()\n\t\tif uiMsg != nil {\n\t\t\tuiMessages = append(uiMessages, *uiMsg)\n\t\t}\n\t}\n\n\treturn &uctypes.UIChat{\n\t\tChatId:     aiChat.ChatId,","sourceCodeStart":799,"sourceCodeEnd":835,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/anthropic/anthropic-convertmessage.go#L799-L835","documentation":"ConvertAIChatToUIChat only converts chats whose native format is the Anthropic Messages API. The guard verifies aiChat.APIType equals uctypes.APIType_AnthropicMessages; passing a chat produced by another provider (OpenAI, Google, etc.) is rejected with the expected and actual API types.","triggerScenarios":"Calling ConvertAIChatToUIChat with an AIChat whose APIType field is anything other than APIType_AnthropicMessages — e.g. a chat built by an OpenAI converter.","commonSituations":"Mixing provider chat objects after refactoring, storing chats in a shared cache without the APIType, or routing the wrong chat to the Anthropic UI converter.","solutions":["Ensure the chat was produced by the Anthropic converter and APIType is APIType_AnthropicMessages","Check APIType before calling and route to the matching provider's ConvertAIChatToUIChat","Fix the code path that sets APIType when constructing the AIChat"],"exampleFix":"// before\nuiChat, err := anthropic.ConvertAIChatToUIChat(aiChat) // APIType=openai\n// after\nif aiChat.APIType == uctypes.APIType_AnthropicMessages {\n    uiChat, err = anthropic.ConvertAIChatToUIChat(aiChat)\n} else {\n    uiChat, err = openai.ConvertAIChatToUIChat(aiChat)\n}","handlingStrategy":"type-guard","validationCode":"if aiChat.APIType != uctypes.APIType_AnthropicMessages {\n    return fmt.Errorf(\"wrong converter for APIType %s\", aiChat.APIType)\n}","typeGuard":"func isAnthropicChat(c uctypes.AIChat) bool {\n    return c.APIType == uctypes.APIType_AnthropicMessages\n}","tryCatchPattern":"if !isAnthropicChat(aiChat) {\n    return nil, fmt.Errorf(\"route %s chats to their provider converter\", aiChat.APIType)\n}\nuiChat, err := anthropic.ConvertAIChatToUIChat(aiChat)","preventionTips":["Store APIType alongside cached chats and dispatch converters by it","Never share one AIChat across provider code paths","Add a switch on APIType that routes to the matching converter"],"tags":["go","anthropic","api-type","mismatch"],"backgroundTag":"api-type-mismatch","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}