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

  1. Read the sanitized message to identify the underlying error class (connection refused, TLS, timeout, HTTP status).
  2. To see the real endpoint during debugging, temporarily log the pre-sanitization error server-side.
  3. Fix the root cause indicated by the sanitized text (network, auth, proxy).
  4. 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

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-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/a56684693bb68970. Report an issue: GitHub.