JuliusBrussee/caveman · error

provider upstream URL path rejected

Error message

provider %q upstream URL path rejected: %w

What it means

This is a wrapped error: parseBaseURL runs validatePathComponents on the configured base URL's Path/RawPath (openaicompat.go:531) and re-wraps any rejection as 'provider %q upstream URL path rejected: %w'. validatePathComponents forbids backslashes, empty interior segments (repeated '//'), dot segments ('.'/'..'), and ambiguous escaped sequences (%2f, %5c, %2e) so a URL cannot change route identity after another decoder or proxy hop.

Solutions

  1. Read the wrapped cause at the end of the message and remove the offending construct (backslash, '//', '.'/'..', or %2f/%5c/%2e) from the base URL path.
  2. Normalize the path to plain '/'-separated segments and confirm it matches the vendor's documented base path.
  3. Re-run ValidateBaseURL; also check ValidateRequestPath on inbound /compat/ routes, which applies the same rules to request paths.

Example fix

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

Strategy: validation

Validate before calling

u, _ := url.Parse(raw)
if err := validatePathComponents(u.Path, u.RawPath); err != nil {
    return fmt.Errorf("base URL path rejected: %w — remove backslashes, '//' runs, dot segments, and %2f/%5c/%2e escapes", err)
}

Type guard

func hasCleanPath(raw string) bool {
    u, err := url.Parse(raw)
    return err == nil && validatePathComponents(u.Path, u.RawPath) == nil
}

Try / catch

if _, err := parseBaseURL(raw, provider); err != nil {
    var cause error
    if errors.As(err, &cause) || true {
        log.Fatalf("fix the base URL path (see wrapped cause): %v", err)
    }
}

Prevention

When it happens

Trigger: Call ResolveUpstreamURL or ValidateBaseURL with a base URL whose path contains e.g. 'https://api.example.com//v1', '.../v1/../v2', a backslash ('https://api.example.com\v1'), or an escaped '%2f'/'%2e' in RawPath. The %w verb reveals the specific cause (backslash / repeated separators / dot segments / ambiguous escape).

Common situations: Hand-edited YAML with double slashes, Windows-style paths pasted with backslashes, or intentionally obfuscated/redirect-style URLs that use encoded slashes to slip past path-based routing.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


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

Appendix: source

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

	}
	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)