labstack/echo · error
%s: %w
Error message
%s: %w
What it means
A wrapping error (fmt.Errorf with %w) from bindData at line 322, produced when unmarshalInputsToField fails. This path handles fields implementing the bindMultipleUnmarshaler interface (UnmarshalParams([]string) error) and their UnmarshalParams call returned an error. The field name is prefixed (e.g. "tags: <inner error>") so the caller knows which field failed, and the inner error is wrapped for errors.Is/As.
Source
Thrown at bind.go:322
if strings.EqualFold(k, inputFieldName) {
inputValue = v
exists = true
break
}
}
}
if !exists {
continue
}
// NOTE: algorithm here is not particularly sophisticated. It probably does not work with absurd types like `**[]*int`
// but it is smart enough to handle niche cases like `*int`,`*[]string`,`[]*int` .
// try unmarshalling first, in case we're dealing with an alias to an array type
if ok, err := unmarshalInputsToField(fm.fieldKind, inputValue, structField); ok {
if err != nil {
return fmt.Errorf("%s: %w", inputFieldName, err)
}
continue
}
if ok, err := unmarshalInputToField(fm.fieldKind, inputValue[0], structField, fm.formatTag); ok {
if err != nil {
return fmt.Errorf("%s: %w", inputFieldName, err)
}
continue
}
// we could be dealing with pointer to slice `*[]string` so dereference it. There are weird OpenAPI generators
// that could create struct fields like that.
if structFieldKind == reflect.Pointer {
structFieldKind = structField.Elem().Kind()
structField = structField.Elem()
}
View on GitHub (pinned to 05489dc173)
Solutions
- Inspect the wrapped error via errors.Unwrap/errors.Is to determine the exact parse failure
- Fix the client input to match the expected format for that field
- Make the UnmarshalParams implementation more lenient or return a clearer error message
Example fix
// custom type returning error from UnmarshalParams
type Tags []string
func (t *Tags) UnmarshalParams(vals []string) error {
if len(vals) > 5 { return errors.New("max 5 tags") }
*t = vals
return nil
}
// error returned: "tags: max 5 tags"
// fix: send <= 5 tags, or raise the limit in UnmarshalParams Defensive patterns
Strategy: try-catch
Validate before calling
// Validate multi-value params before they reach UnmarshalParams
func validateSliceValues(vals []string, max int) error {
if len(vals) > max {
return fmt.Errorf("too many values: %d > %d", len(vals), max)
}
return nil
} Try / catch
if err := c.Bind(&req); err != nil {
var he *echo.HTTPError
if errors.As(err, &he) || strings.Contains(err.Error(), ":") {
// field-level bind error; extract field name from prefix
fieldName := strings.SplitN(err.Error(), ":", 2)[0]
return echo.NewHTTPError(http.StatusBadRequest, "invalid value for "+fieldName)
}
return err
} Prevention
- Make UnmarshalParams implementations return clear, specific error messages
- Validate input length and format early in UnmarshalParams
- Document the expected multi-value format in your API spec
When it happens
Trigger: Binding multiple query/form values (e.g. ?tag=a&tag=b) into a field whose type implements UnmarshalParams([]string) error, and the implementation returns an error such as invalid format, too many values, or domain validation failure.
Common situations: Custom slice or collection types with an UnmarshalParams implementation enforcing constraints (max items, allowed values). Custom enum or time types parsing multiple inputs.
Related errors
- binding element must be a struct
- query/param/form tags are not allowed with anonymous struct
- unknown type
- binding to multipart.FileHeader struct is not supported, use
- failed to parse form value, key: %s, err: %w
AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04).
Data as JSON: /data/errors/ee2535efa9ce40d0.json.
Report an issue: GitHub.