labstack/echo · error
failed to parse form value, key: %s, err: %w
Error message
failed to parse form value, key: %s, err: %w
What it means
Returned by echo.FormValue[T] (binder_generic.go:213-218) when the underlying c.FormValues() call failed, wrapped with the offending key. The generic parse never started — the request body could not be parsed as form data. Distinguish from ErrNonExistentKey which is returned only when parsing succeeds but the key is absent.
Source
Thrown at binder_generic.go:217
return result, nil
}
// FormValue extracts and parses a single form value from the request by key.
// It returns the typed value and an error if binding fails. Returns ErrNonExistentKey if parameter not found.
//
// Empty String Handling:
//
// If the form field exists but has an empty value, the zero value of type T is returned
// with no error. For example, an empty form field returns (0, nil) for int types.
// This differs from standard library behavior where parsing empty strings returns errors.
// To treat empty values as errors, validate the result separately or check the raw value.
//
// See ParseValue for supported types and options
func FormValue[T any](c *Context, key string, opts ...any) (T, error) {
formValues, err := c.FormValues()
if err != nil {
var zero T
return zero, fmt.Errorf("failed to parse form value, key: %s, err: %w", key, err)
}
values, ok := formValues[key]
if !ok {
var zero T
return zero, ErrNonExistentKey
}
if len(values) == 0 {
var zero T
return zero, nil
}
value := values[0]
v, err := ParseValue[T](value, opts...)
if err != nil {
return v, NewBindingError(key, []string{value}, "form value", err)
}
return v, nil
}
View on GitHub (pinned to 05489dc173)
Solutions
- Ensure the client sends application/x-www-form-urlencoded or multipart/form-data
- Raise MaxRequestSize / multipart memory limits if body parsing hit a cap
- For JSON clients use c.Bind(&struct{}) instead of FormValue
Example fix
// before
page, err := echo.FormValue[int](c, "page")
// after — validate content type, and switch to JSON binding for JSON clients:
if !isFormContent(c) {
return c.JSON(http.StatusUnsupportedMediaType, map[string]string{"error": "form content-type required"})
}
page, err := echo.FormValue[int](c, "page") Defensive patterns
Strategy: try-catch
Validate before calling
ct := c.Request().Header.Get("Content-Type")
if !strings.HasPrefix(ct, "application/x-www-form-urlencoded") && !strings.HasPrefix(ct, "multipart/form-data") {
return c.JSON(http.StatusUnsupportedMediaType, map[string]string{"error": "form content-type required"})
} Try / catch
v, err := echo.FormValue[int](c, "page")
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid form: " + err.Error()})
} Prevention
- Document the expected Content-Type on the endpoint
- Validate Content-Type at the handler boundary
- Use c.Bind for JSON clients
When it happens
Trigger: Calling FormValue[int](c, "page") on a request whose multipart body is malformed, whose Content-Type is not form/multipart, or whose multipart.Parse returned an error (bad boundary, body too large).
Common situations: Wrong Content-Type (client sending JSON to a form handler), exceeded MaxRequestSize / multipart memory, corrupted multipart boundary, truncated body.
Related errors
- binding element must be a struct
- failed to parse form values, key: %s, err: %w
- query/param/form tags are not allowed with anonymous struct
- unknown type
- binding to multipart.FileHeader struct is not supported, use
AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04).
Data as JSON: /data/errors/979c1632f08942b6.json.
Report an issue: GitHub.