air-verse/air · warning
proxy handler: bad form
Error message
proxy handler: bad form
What it means
proxyHandler must parse the incoming request's form data so it can re-encode the body when forwarding. If r.ParseForm fails (malformed query string or form body), the proxy responds with HTTP 500 and this fixed message.
Source
Thrown at runner/proxy.go:157
page := buf.String()
// the script will be injected before the end of the body tag. In case the tag is missing, the injection will be skipped with no error.
body := strings.LastIndex(page, "</body>")
if body == -1 {
return page, decoded, nil
}
script := "<script>" + ProxyScript + "</script>"
return page[:body] + script + page[body:], decoded, nil
}
func (p *Proxy) proxyHandler(w http.ResponseWriter, r *http.Request) {
appURL := r.URL
appURL.Scheme = "http"
appURL.Host = fmt.Sprintf("localhost:%d", p.config.AppPort)
if err := r.ParseForm(); err != nil {
http.Error(w, "proxy handler: bad form", http.StatusInternalServerError)
return
}
var body io.Reader
if len(r.Form) > 0 {
body = strings.NewReader(r.Form.Encode())
} else {
body = r.Body
}
req, err := http.NewRequest(r.Method, appURL.String(), body)
if err != nil {
http.Error(w, "proxy handler: unable to create request", http.StatusInternalServerError)
return
}
// Copy the headers from the original request
for name, values := range r.Header {
for _, value := range values {
req.Header.Add(name, value)View on GitHub (pinned to 71ea1dee05)
Solutions
- URL-encode query parameters properly in the client (encodeURIComponent / url.Values.Encode)
- Fix malformed percent-escapes in the request URL (e.g. use %25 for a literal %)
- Reproduce the failing URL and check its query string with url.ParseRequestURI
- Send a JSON body with correct Content-Type instead of a form if that suits the API
Example fix
// before (client)
fetch('/api?q=100%')
// after
fetch('/api?q=' + encodeURIComponent('100%')) Defensive patterns
Strategy: validation
Validate before calling
// validate outgoing URLs in the client
u, err := url.Parse(rawURL)
if err != nil || strings.Contains(u.RawQuery, "%") {
// ensure every % is part of a valid escape
if err != nil || regexp.MustCompile(`%(?![0-9A-Fa-f]{2})`).MatchString(u.RawQuery) {
return fmt.Errorf("malformed query string: %q", rawURL)
}
} Try / catch
resp, err := http.Get(url)
if err != nil && resp != nil && resp.StatusCode == 500 {
body, _ := io.ReadAll(resp.Body)
if strings.Contains(string(body), "proxy handler: bad form") {
// fix percent-encoding in the request URL/body
}
} Prevention
- Always encodeURIComponent (JS) or url.Values.Encode (Go) query params
- Escape literal % as %25 in URLs
- Never build query strings by string concatenation
- Sanitize user input before putting it in URLs
When it happens
Trigger: A client sends a request to the air proxy whose URL query string or application/x-www-form-urlencoded body is malformed (e.g. bad percent-encoding like `%zz`), causing http.Request.ParseForm to return an error.
Common situations: Frontend code building query strings with improperly escaped special characters (% not encoded as %25); manually constructed URLs with raw `#`, spaces, or broken percent-encoding; test tools sending deliberately bad forms.
Related errors
- proxy inject: failed to init gzip reader: %w
- proxy inject: failed to read body from http response: %w
- proxy handler: unable to create request
AI-assisted analysis of air-verse/air@71ea1dee05 (2026-08-31).
Data as JSON: /api/errors/86fd435a11c4a8d9.
Report an issue: GitHub.