{"id":"979c1632f08942b6","repo":"labstack/echo","slug":"failed-to-parse-form-value-key-s-err-w","errorCode":null,"errorMessage":"failed to parse form value, key: %s, err: %w","messagePattern":"failed to parse form value, key: (.+?), err: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"binder_generic.go","lineNumber":217,"sourceCode":"\treturn result, nil\n}\n\n// FormValue extracts and parses a single form value from the request by key.\n// It returns the typed value and an error if binding fails. Returns ErrNonExistentKey if parameter not found.\n//\n// Empty String Handling:\n//\n//\tIf the form field exists but has an empty value, the zero value of type T is returned\n//\twith no error. For example, an empty form field returns (0, nil) for int types.\n//\tThis differs from standard library behavior where parsing empty strings returns errors.\n//\tTo treat empty values as errors, validate the result separately or check the raw value.\n//\n// See ParseValue for supported types and options\nfunc FormValue[T any](c *Context, key string, opts ...any) (T, error) {\n\tformValues, err := c.FormValues()\n\tif err != nil {\n\t\tvar zero T\n\t\treturn zero, fmt.Errorf(\"failed to parse form value, key: %s, err: %w\", key, err)\n\t}\n\tvalues, ok := formValues[key]\n\tif !ok {\n\t\tvar zero T\n\t\treturn zero, ErrNonExistentKey\n\t}\n\tif len(values) == 0 {\n\t\tvar zero T\n\t\treturn zero, nil\n\t}\n\tvalue := values[0]\n\tv, err := ParseValue[T](value, opts...)\n\tif err != nil {\n\t\treturn v, NewBindingError(key, []string{value}, \"form value\", err)\n\t}\n\treturn v, nil\n}\n","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/binder_generic.go#L199-L235","documentation":"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.","triggerScenarios":"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).","commonSituations":"Wrong Content-Type (client sending JSON to a form handler), exceeded MaxRequestSize / multipart memory, corrupted multipart boundary, truncated body.","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"],"exampleFix":"// before\npage, err := echo.FormValue[int](c, \"page\")\n// after — validate content type, and switch to JSON binding for JSON clients:\nif !isFormContent(c) {\n    return c.JSON(http.StatusUnsupportedMediaType, map[string]string{\"error\": \"form content-type required\"})\n}\npage, err := echo.FormValue[int](c, \"page\")","handlingStrategy":"try-catch","validationCode":"ct := c.Request().Header.Get(\"Content-Type\")\nif !strings.HasPrefix(ct, \"application/x-www-form-urlencoded\") && !strings.HasPrefix(ct, \"multipart/form-data\") {\n    return c.JSON(http.StatusUnsupportedMediaType, map[string]string{\"error\": \"form content-type required\"})\n}","typeGuard":null,"tryCatchPattern":"v, err := echo.FormValue[int](c, \"page\")\nif err != nil {\n    return c.JSON(http.StatusBadRequest, map[string]string{\"error\": \"invalid form: \" + err.Error()})\n}","preventionTips":["Document the expected Content-Type on the endpoint","Validate Content-Type at the handler boundary","Use c.Bind for JSON clients"],"tags":["binding","form"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}