wavetermdev/waveterm · info
%s
Error message
%s
What it means
sanitizeHostnameInError rewrites internal/cloud hostnames (the DefaultAIEndpoint) out of error messages before surfacing them, replacing them with "AI service"/"host". The final error is rebuilt with fmt.Errorf("%s", errStr). This error is the generic sanitized error text — the message content comes from the underlying transport/API error, with the hostname stripped.
Source
Thrown at pkg/aiusechat/anthropic/anthropic-backend.go:357
case map[string]interface{}:
return json.RawMessage(raw), nil
default:
return nil, fmt.Errorf("tool input is not an object")
}
}
// sanitizeHostnameInError removes the Wave cloud hostname from error messages
func sanitizeHostnameInError(err error) error {
if err == nil {
return nil
}
errStr := err.Error()
parsedURL, parseErr := url.Parse(uctypes.DefaultAIEndpoint)
if parseErr == nil && parsedURL.Host != "" && strings.Contains(errStr, parsedURL.Host) {
errStr = strings.ReplaceAll(errStr, uctypes.DefaultAIEndpoint, "AI service")
errStr = strings.ReplaceAll(errStr, parsedURL.Host, "host")
}
return fmt.Errorf("%s", errStr)
}
// makeThinkingOpts creates thinking options based on level and max tokens
func makeThinkingOpts(thinkingLevel string, maxTokens int) *anthropicThinkingOpts {
if thinkingLevel != uctypes.ThinkingLevelMedium && thinkingLevel != uctypes.ThinkingLevelHigh {
return nil
}
maxThinkingBudget := int(float64(maxTokens) * 0.75)
// If 75% of maxTokens is less than minimum, disable thinking
if maxThinkingBudget < AnthropicMinThinkingBudget {
return nil
}
// Use the smaller of our default budget or 75% of maxTokens
thinkingBudget := AnthropicThinkingBudget
if thinkingBudget > maxThinkingBudget {View on GitHub (pinned to a4447c1563)
Solutions
- Read the sanitized message to identify the underlying error class (connection refused, TLS, timeout, HTTP status).
- To see the real endpoint during debugging, temporarily log the pre-sanitization error server-side.
- Fix the root cause indicated by the sanitized text (network, auth, proxy).
- If the sanitization makes errors too opaque for your users, include a correlation/request ID in the unsanitized server-side log.
Example fix
// pattern
err := runAnthropic(ctx)
if err != nil {
log.Printf("[server-only] anthropic failure at %s", err) // unsanitized source
return sanitizeHostnameInError(err)
} Defensive patterns
Strategy: try-catch
Try / catch
err := doRequest(ctx)
if err != nil {
// sanitized text: match on error classes, not hostnames
switch {
case strings.Contains(err.Error(), "connection refused"), strings.Contains(err.Error(), "no such host"):
return retryWithBackoff(ctx)
case strings.Contains(err.Error(), "status"):
return handleHTTPFailure(err)
}
return err
} Prevention
- Log the unsanitized error server-side with a correlation ID before sanitizing
- Match user-facing handling on error classes, not endpoint hostnames
- Remember the endpoint host will appear as "host"/"AI service" in surfaced errors
When it happens
Trigger: Any upstream error from the Anthropic request path (connection failures, TLS errors, HTTP errors) whose message contains the default AI endpoint host is passed through sanitizeHostnameInError; the returned error is the sanitized string. There is no failure condition here itself — it's the re-wrapping of any error text.
Common situations: DNS/connection errors to the AI endpoint shown to users without leaking internal hostnames; proxy misconfigurations surfacing the endpoint URL; users debugging why errors say "host" instead of a real hostname.
Related errors
- ai:model is required
- no data available for base64 extraction
- toolResults cannot be empty
- invalid accumulated tool input JSON: %w
- tool input is not an object
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/a56684693bb68970.
Report an issue: GitHub.