multica-ai/multica · error

invalid MULTICA_SERVER_URL: %w

Error message

invalid MULTICA_SERVER_URL: %w

What it means

NormalizeServerBaseURL failed at the first step: url.Parse rejected the trimmed MULTICA_SERVER_URL value. The Go URL parser is lenient, so this only happens with genuinely malformed input (control characters, an unmatched '%' escape, or embedded whitespace that survives trimming at the ends). The error wraps the parse error so the exact position is visible.

Source

Thrown at server/internal/daemon/config.go:579

// isOfficialCloudServer reports whether the resolved server base URL points
// at Multica's hosted cloud. Used to pick the auto-update default: cloud
// users run a server that publishes the matching CLI release, so opt-in
// self-update is safe; self-host users may run a fork or pin to an older
// server, so the default flips to off. Matching is host-only and
// case-insensitive — port and path are ignored.
func isOfficialCloudServer(baseURL string) bool {
	u, err := url.Parse(strings.TrimSpace(baseURL))
	if err != nil {
		return false
	}
	return strings.EqualFold(u.Hostname(), officialCloudHost)
}

// NormalizeServerBaseURL converts a WebSocket or HTTP URL to a base HTTP URL.
func NormalizeServerBaseURL(raw string) (string, error) {
	u, err := url.Parse(strings.TrimSpace(raw))
	if err != nil {
		return "", fmt.Errorf("invalid MULTICA_SERVER_URL: %w", err)
	}
	switch u.Scheme {
	case "ws":
		u.Scheme = "http"
	case "wss":
		u.Scheme = "https"
	case "http", "https":
	default:
		return "", fmt.Errorf("MULTICA_SERVER_URL must use ws, wss, http, or https")
	}
	if u.Path == "/ws" {
		u.Path = ""
	}
	u.RawPath = ""
	u.RawQuery = ""
	u.Fragment = ""
	return strings.TrimRight(u.String(), "/"), nil
}

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Print the value with %q to reveal invisible characters: it usually shows a quote, control rune, or raw %
  2. Re-enter the URL as plain https://host[:port] with no quotes or escapes inside the value
  3. URL-encode any legitimate special characters (a '%' must be '%25')
Defensive patterns

Strategy: validation

Validate before calling

// Validate the env var before passing it on.
raw := strings.TrimSpace(os.Getenv("MULTICA_SERVER_URL"))
if u, err := url.Parse(raw); err != nil {
    return fmt.Errorf("MULTICA_SERVER_URL %q is not a parseable URL: %w", raw, err)
}

Try / catch

Handle at config-load time: catch the error, echo the raw value with %q so hidden characters are visible, and prompt the user to re-enter it.

Prevention

When it happens

Trigger: Setting MULTICA_SERVER_URL to a value containing a raw '%' (e.g. a password with %zz in it), control characters from a copy-paste, or a trailing/leading quote from shell wrapping. Note that values like 'localhost:8080' parse fine and instead fail the scheme check (error 872).

Common situations: Copy-paste from docs with smart quotes/invisible characters, shell quoting mistakes leaving a stray quote inside the value, secrets or malformed escapes embedded in the URL.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/025373e8a8b44b00. Report an issue: GitHub.