wavetermdev/waveterm · error
chatOpts.ClientId is required
Error message
chatOpts.ClientId is required
What it means
buildAnthropicHTTPRequest requires chatOpts.ClientId, which identifies the calling client/block for the request. An empty ClientId breaks request construction and possibly downstream authorization/bookkeeping, so the code rejects it before building the HTTP request.
Source
Thrown at pkg/aiusechat/anthropic/anthropic-convertmessage.go:37
"github.com/google/uuid"
"github.com/wavetermdev/waveterm/pkg/aiusechat/chatstore"
"github.com/wavetermdev/waveterm/pkg/aiusechat/uctypes"
"github.com/wavetermdev/waveterm/pkg/util/logutil"
"github.com/wavetermdev/waveterm/pkg/util/utilfn"
"github.com/wavetermdev/waveterm/pkg/wavebase"
)
// these conversions are based off the anthropic spec
// and the aiprompts/aisdk-uimessage-type.md doc (v5)
// buildAnthropicHTTPRequest creates a complete HTTP request for the Anthropic API
func buildAnthropicHTTPRequest(ctx context.Context, msgs []anthropicInputMessage, chatOpts uctypes.WaveChatOpts) (*http.Request, error) {
opts := chatOpts.Config
if opts.Model == "" {
return nil, errors.New("ai:model is required")
}
if chatOpts.ClientId == "" {
return nil, errors.New("chatOpts.ClientId is required")
}
// Set defaults
endpoint := opts.Endpoint
if endpoint == "" {
return nil, errors.New("ai:endpoint is required")
}
maxTokens := opts.MaxTokens
if maxTokens <= 0 {
maxTokens = AnthropicDefaultMaxTokens
}
// Convert messages to clear FileName fields from Source blocks
convertedMsgs := make([]anthropicInputMessage, len(msgs))
for i, msg := range msgs {
convertedMsgs[i] = convertMessageForAPI(msg)
}View on GitHub (pinned to a4447c1563)
Solutions
- Populate chatOpts.ClientId from the block/context id before invoking the chat step.
- Use the standard entry point that assembles WaveChatOpts from block metadata rather than hand-building opts.
- Assert ClientId non-empty in the caller with a descriptive error.
Example fix
// before
opts := uctypes.WaveChatOpts{ChatId: chatId, Config: cfg}
// after
opts := uctypes.WaveChatOpts{ChatId: chatId, ClientId: blockId, Config: cfg} Defensive patterns
Strategy: validation
Validate before calling
if chatOpts.ClientId == "" {
return fmt.Errorf("config error: ClientId (block id) required for anthropic chat")
} Type guard
func hasClientId(o uctypes.WaveChatOpts) bool { return o.ClientId != "" } Try / catch
if err := validateChatOpts(chatOpts); err != nil {
return err // fails fast on empty ClientId before the API call
} Prevention
- Derive WaveChatOpts from the block context so ClientId is filled automatically.
- Never hand-build WaveChatOpts literals outside a shared constructor.
- Log opts at debug level to spot empty ids during development.
When it happens
Trigger: RunAnthropicChatStep invoked with WaveChatOpts whose ClientId field is empty — typically when the caller builds opts manually instead of deriving them from the block context.
Common situations: Background/standalone runners calling the AI step without a block context; tests constructing WaveChatOpts literal; a refactor that renamed or stopped populating ClientId upstream.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- ai:model is required
- ai:endpoint is required
- --conn parameter is required
- No tab view found for the given webContents id
- cannot call ${methodName}: no web endpoint
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/6c4744f7fe84e0a0.
Report an issue: GitHub.