JuliusBrussee/caveman · error

provider upstream URL must not include a fragment

Error message

provider %q upstream URL must not include a fragment

What it means

parseBaseURL rejects a base URL that contains a '#fragment' component (openaicompat.go:528). A fragment is a client-side-only locator; it is meaningless on an HTTP request line and would either be dropped or corrupt the joined upstream URL, so the adapter fails closed instead of ignoring it silently.

Solutions

  1. Delete everything from the '#' character onward in the configured base URL.
  2. Verify the remaining value is 'scheme://host[:port]/path' and re-run ValidateBaseURL.
  3. If the fragment was meant to select a route/section, encode that intent in the path or a config option instead.

Example fix

// before
base_url: https://api.example.com/v1#chat
// after
base_url: https://api.example.com/v1
Defensive patterns

Strategy: validation

Validate before calling

if u, err := url.Parse(raw); err == nil && u.Fragment != "" {
    return fmt.Errorf("base URL must not include a #fragment; got %q", u.Fragment)
}

Type guard

func hasFragment(raw string) bool {
    u, err := url.Parse(raw)
    return err == nil && u.Fragment != ""
}

Try / catch

if err := ValidateBaseURL(raw); err != nil {
    if strings.Contains(err.Error(), "fragment") {
        log.Fatal("remove everything after '#' in base_url")
    }
    log.Fatal(err)
}

Prevention

When it happens

Trigger: Configure a compat provider base URL like 'https://api.example.com/v1#production' or paste a URL copied from a browser address bar that includes an anchor, then call ResolveUpstreamURL or ValidateBaseURL.

Common situations: Pasting URLs directly from browser tabs (anchors like #models or #settings included), or documentation links where the anchor was part of the copy.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/28aee1b53029f625. Report an issue: GitHub.

Appendix: source

Thrown at proxy/providers/openaicompat/openaicompat.go:529

func parseBaseURL(raw, provider string) (*url.URL, error) {
	if strings.TrimSpace(raw) == "" {
		return nil, fmt.Errorf("provider %q has no configured upstream URL", provider)
	}
	u, err := url.Parse(strings.TrimSpace(raw))
	if err != nil {
		return nil, err
	}
	if u.Scheme != "http" && u.Scheme != "https" {
		return nil, fmt.Errorf("provider %q upstream URL scheme %q is not allowed", provider, u.Scheme)
	}
	if !u.IsAbs() || u.Host == "" || u.Hostname() == "" {
		return nil, fmt.Errorf("provider %q upstream URL must be an absolute URL with a host", provider)
	}
	if u.User != nil {
		return nil, fmt.Errorf("provider %q upstream URL must not include userinfo", provider)
	}
	if u.Fragment != "" {
		return nil, fmt.Errorf("provider %q upstream URL must not include a fragment", provider)
	}
	if err := validatePathComponents(u.Path, u.RawPath); err != nil {
		return nil, fmt.Errorf("provider %q upstream URL path rejected: %w", provider, err)
	}
	return u, nil
}

View on GitHub (pinned to 3ee70a1026)