JuliusBrussee/caveman · error

request URL is missing

Error message

request URL is missing

What it means

ValidateRequestPath checks the original request URL (including RawPath) for ambiguous encodings before adapter selection. It returns this error when called with a nil *url.URL, meaning the caller has no URL to validate. Gateways call it up front; the adapter checks are a second fail-closed boundary for direct callers.

Solutions

  1. Parse the incoming request URI with url.ParseRequestURI and check its error before validating
  2. Ensure req.URL is populated before gateway validation
  3. Skip/short-circuit when there is genuinely no URL, but reject the HTTP request with 400
  4. In tests, always construct a URL via url.Parse

Example fix

// before
err := ValidateRequestPath(req.URL)

// after
if req == nil || req.URL == nil {
    return fmt.Errorf("bad request: missing URL")
}
err := ValidateRequestPath(req.URL)
Defensive patterns

Strategy: validation

Validate before calling

if req == nil || req.URL == nil {
    return errors.New("missing request URL")
}
if err := ValidateRequestPath(req.URL); err != nil {
    return err
}

Type guard

func hasRequestURL(req *http.Request) bool { return req != nil && req.URL != nil }

Try / catch

if err := ValidateRequestPath(req.URL); err != nil {
    http.Error(w, "invalid request path", http.StatusBadRequest)
    return
}

Prevention

When it happens

Trigger: Calling ValidateRequestPath(nil); passing a URL obtained from a request whose URL was never populated; calling before parsing the raw request URI.

Common situations: Gateway middleware invoked on malformed requests where url.Parse failed earlier; tests passing nil directly; proxy hops dropping the URL field.

Related errors


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

Appendix: source

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

		return nil, err
	}
	if !strings.HasPrefix(req.URL.Path, a.prefix+"/") {
		return nil, fmt.Errorf("compat route %q does not match prefix %q", req.URL.Path, a.prefix+"/")
	}
	path := strings.TrimPrefix(req.URL.Path, a.prefix)
	base.Path = joinCompatPath(base.Path, path)
	base.RawPath = ""
	base.RawQuery = joinCompatQuery(base.RawQuery, req.URL.RawQuery)
	return base, nil
}

// ValidateRequestPath rejects ambiguous path encodings before adapter selection.
// Gateways call this with the original URL (including RawPath), while the
// adapter MatchRoute/ResolveUpstreamURL checks provide a second fail-closed
// boundary for direct callers.
func ValidateRequestPath(u *url.URL) error {
	if u == nil {
		return fmt.Errorf("request URL is missing")
	}
	if !strings.HasPrefix(u.Path, "/compat/") {
		return nil
	}
	return validateCompatPath(u.Path, u.RawPath)
}

func validateCompatPath(path, rawPath string) error {
	if !strings.HasPrefix(path, "/compat/") {
		return nil
	}
	if err := validatePathComponents(path, rawPath); err != nil {
		return fmt.Errorf("compat route path rejected: %w", err)
	}
	return nil
}

func validatePathComponents(path, rawPath string) error {

View on GitHub (pinned to 3ee70a1026)