plandex-ai/plandex · error

Error creating request for proxy

Error message

Error creating request for proxy

What it means

proxyRequest builds an outbound http.NewRequestWithContext to clone the incoming request and forward it to the instance IP hosting the plan. If that construction fails, the handler returns HTTP 500 "Error creating request for proxy". http.NewRequestWithContext errors on an invalid URL or an unparsable method — almost always a malformed proxy URL.

Source

Thrown at app/server/handlers/proxy_helper.go:66

		proxyUrl := fmt.Sprintf("http://%s:%s/plans/%s/%s/%s", modelStream.InternalIp, os.Getenv("PORT"), planId, branch, method)
		proxyUrl += "?proxy=true"

		log.Printf("Proxy url: %s\n", proxyUrl)
		proxyRequest(w, r, proxyUrl)
		return
	}
}

func proxyRequest(w http.ResponseWriter, originalRequest *http.Request, url string) {
	client := &http.Client{
		Timeout: time.Second * 10,
	}

	// Create a new request based on the original request
	req, err := http.NewRequestWithContext(originalRequest.Context(), originalRequest.Method, url, originalRequest.Body)
	if err != nil {
		log.Printf("Error creating request for proxy: %v\n", err)
		http.Error(w, "Error creating request for proxy", http.StatusInternalServerError)
		return
	}

	// Copy the headers from the original request to the new request
	for name, headers := range originalRequest.Header {
		for _, h := range headers {
			req.Header.Add(name, h)
		}
	}

	// Copy the body from the original request to the new request if it's a POST or PUT
	if originalRequest.Method == http.MethodPost || originalRequest.Method == http.MethodPut {
		req.Body = originalRequest.Body
	}

	// Make the request
	resp, err := client.Do(req)
	if err != nil {

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the server log for the exact NewRequestWithContext error — it names the malformed URL.
  2. Log/validate the composed proxyUrl before creating the request; url.Parse it to catch malformed pieces.
  3. Ensure InternalIp is a bare IP/host set during stream registration; reject empty values earlier.
  4. Use url.PathEscape for planId/branch/method path segments and validate PORT is set at startup.
  5. Verify with url.Parse(proxyUrl) in tests that all lifecycle paths produce valid URLs.

Example fix

// before
proxyUrl := fmt.Sprintf("http://%s:%s/plans/%s/%s/%s", modelStream.InternalIp, os.Getenv("PORT"), planId, branch, method)
req, err := http.NewRequestWithContext(originalRequest.Context(), originalRequest.Method, url, originalRequest.Body)
// after
if modelStream.InternalIp == "" {
    http.Error(w, "Internal IP missing for plan stream", http.StatusBadGateway)
    return
}
port := os.Getenv("PORT")
if port == "" { port = "8080" }
proxyUrl := fmt.Sprintf("http://%s:%s/plans/%s/%s/%s",
    modelStream.InternalIp, port,
    url.PathEscape(planId), url.PathEscape(branch), url.PathEscape(method))
if _, err := url.Parse(proxyUrl); err != nil {
    http.Error(w, "Invalid proxy URL", http.StatusBadGateway)
    return
}
req, err := http.NewRequestWithContext(originalRequest.Context(), originalRequest.Method, proxyUrl, originalRequest.Body)
Defensive patterns

Strategy: validation

Validate before calling

// server-side: validate URL parts before building the request
if modelStream.InternalIp == "" || os.Getenv("PORT") == "" {
    http.Error(w, "Proxy target not configured", http.StatusBadGateway)
    return
}
if _, err := url.Parse(fmt.Sprintf("http://%s:%s", modelStream.InternalIp, os.Getenv("PORT"))); err != nil {
    http.Error(w, "Invalid proxy target", http.StatusBadGateway)
    return
}

Try / catch

// caller of the proxied endpoint
try {
  const res = await fetch(`/plans/${planId}/${branch}/connect`);
  if (res.status === 500) console.error('Proxy misconfigured — check server logs for URL error');
} catch (e) { console.error(e); }

Prevention

When it happens

Trigger: modelStream.InternalIp empty or malformed, producing a bad URL like "http://:8080/plans/..."; planId/branch/method containing characters that break URL formatting (spaces, slashes, control chars); os.Getenv("PORT") empty yielding an invalid host:port; context already canceled passed to NewRequestWithContext (rare).

Common situations: Internal IP not set on the stream row (registration bug); un-encoded path segments from user input interpolated into the URL; PORT env var unset in a new deployment; IPv6 or hostname with scheme accidentally stored in InternalIp.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/bea2231fb437c474. Report an issue: GitHub.