{"id":"cd42847e8b88280e","repo":"gin-gonic/gin","slug":"q-is-not-valid-value-for-s","errorCode":null,"errorMessage":"%q is not valid value for %s","messagePattern":"%q is not valid value for (.+?)","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"binding/form_mapping.go","lineNumber":302,"sourceCode":"\t\t\t// pre-process the default value for multi if present\n\t\t\tcfTag := field.Tag.Get(\"collection_format\")\n\t\t\tif cfTag == \"\" || cfTag == \"multi\" {\n\t\t\t\tvs = strings.Split(opt.defaultValue, \",\")\n\t\t\t}\n\t\t}\n\n\t\tif ok, err = trySetUsingParser(vs[0], value, opt.parser); ok {\n\t\t\treturn ok, err\n\t\t} else if ok, err = trySetCustom(vs[0], value); ok {\n\t\t\treturn ok, err\n\t\t}\n\n\t\tif vs, err = trySplit(vs, field); err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tif len(vs) != value.Len() {\n\t\t\treturn false, fmt.Errorf(\"%q is not valid value for %s\", vs, value.Type().String())\n\t\t}\n\n\t\treturn true, setArray(vs, value, field, opt)\n\tdefault:\n\t\tvar val string\n\t\tif !ok || len(vs) == 0 || (len(vs) > 0 && vs[0] == \"\") {\n\t\t\tval = opt.defaultValue\n\t\t} else if len(vs) > 0 {\n\t\t\tval = vs[0]\n\t\t}\n\n\t\tif ok, err = trySetUsingParser(val, value, opt.parser); ok {\n\t\t\treturn ok, err\n\t\t} else if ok, err = trySetCustom(val, value); ok {\n\t\t\treturn ok, err\n\t\t}\n\t\treturn true, setWithProperType(val, value, field, opt)\n\t}","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/gin-gonic/gin/blob/34dac209ffb6ef85cc78c5d217bbb7ad001d68fd/binding/form_mapping.go#L284-L320","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Change the field to a slice ([]string) so it accepts any count, then validate length explicitly.","Keep the fixed array but make clients send exactly N values; document and validate the contract before binding.","If you used collection_format csv, ensure the comma-separated list splits to exactly N elements."],"exampleFix":"// before\ntype Q struct {\n    Coords [3]float64 `form:\"coords\"`\n}\n// after\ntype Q struct {\n    Coords []float64 `form:\"coords\"`\n}\n// then: if len(q.Coords) != 3 { c.AbortWithStatus(400) }","handlingStrategy":"validation","validationCode":"// before binding, count form values and compare to array length\nif vs, ok := c.Request.Form[\"coords\"]; ok && len(vs) != N {\n    c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{\"error\": fmt.Sprintf(\"coords must have %d values\", N)})\n    return\n}","typeGuard":null,"tryCatchPattern":"if err := c.ShouldBind(&q); err != nil {\n    if strings.Contains(err.Error(), \"is not valid value for\") {\n        // wrong number of values for fixed array; switch to slice or fix client\n    }\n}","preventionTips":["Prefer slices for variable-length form inputs.","Validate the value count explicitly when you must use a fixed array.","Document the exact count contract to clients."],"tags":["binding","form","array","go"],"analyzedSha":"34dac209ffb6ef85cc78c5d217bbb7ad001d68fd","analyzedAt":"2026-08-04T21:26:18.438Z","schemaVersion":2}