gin-gonic/gin · error

%q is not valid value for %s

Error message

%q is not valid value for %s

What it means

Returned by setByForm's reflect.Array branch (binding/form_mapping.go:302) when the number of values resolved for a form key does not equal the fixed length of the destination array. Arrays can't be resized, so a count mismatch is fatal — slices are the resizable alternative.

Source

Thrown at binding/form_mapping.go:302

			// pre-process the default value for multi if present
			cfTag := field.Tag.Get("collection_format")
			if cfTag == "" || cfTag == "multi" {
				vs = strings.Split(opt.defaultValue, ",")
			}
		}

		if ok, err = trySetUsingParser(vs[0], value, opt.parser); ok {
			return ok, err
		} else if ok, err = trySetCustom(vs[0], value); ok {
			return ok, err
		}

		if vs, err = trySplit(vs, field); err != nil {
			return false, err
		}

		if len(vs) != value.Len() {
			return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String())
		}

		return true, setArray(vs, value, field, opt)
	default:
		var val string
		if !ok || len(vs) == 0 || (len(vs) > 0 && vs[0] == "") {
			val = opt.defaultValue
		} else if len(vs) > 0 {
			val = vs[0]
		}

		if ok, err = trySetUsingParser(val, value, opt.parser); ok {
			return ok, err
		} else if ok, err = trySetCustom(val, value); ok {
			return ok, err
		}
		return true, setWithProperType(val, value, field, opt)
	}

View on GitHub (pinned to 34dac209ff)

Solutions

  1. Change the field to a slice ([]string) so it accepts any count, then validate length explicitly.
  2. Keep the fixed array but make clients send exactly N values; document and validate the contract before binding.
  3. If you used collection_format csv, ensure the comma-separated list splits to exactly N elements.

Example fix

// before
type Q struct {
    Coords [3]float64 `form:"coords"`
}
// after
type Q struct {
    Coords []float64 `form:"coords"`
}
// then: if len(q.Coords) != 3 { c.AbortWithStatus(400) }
Defensive patterns

Strategy: validation

Validate before calling

// before binding, count form values and compare to array length
if vs, ok := c.Request.Form["coords"]; ok && len(vs) != N {
    c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("coords must have %d values", N)})
    return
}

Try / catch

if err := c.ShouldBind(&q); err != nil {
    if strings.Contains(err.Error(), "is not valid value for") {
        // wrong number of values for fixed array; switch to slice or fix client
    }
}

Prevention

When it happens

Trigger: Binding query/form into a struct field typed [3]string with a form value of tags=a,b (2 values) or tags=a,b,c,d (4); using collection_format csv but providing a comma list of the wrong length.

Common situations: Hard-coding array length for a fixed contract ("pass exactly 3 coordinates") and a client sending a different count; changing a slice to an array and forgetting to update clients.

Related errors


AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04). Data as JSON: /data/errors/cd42847e8b88280e.json. Report an issue: GitHub.