{"record":{"id":"4a9b08324a2f15f0","repo":"jmoiron/sqlx","slug":"empty-slice-passed-to-in-query","errorCode":null,"errorMessage":"empty slice passed to 'in' query","messagePattern":"empty slice passed to 'in' query","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"bind.go","lineNumber":180,"sourceCode":"\n\tfor i, arg := range args {\n\t\tif a, ok := arg.(driver.Valuer); ok {\n\t\t\tvar err error\n\t\t\targ, err = a.Value()\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", nil, err\n\t\t\t}\n\t\t}\n\n\t\tif v, ok := asSliceForIn(arg); ok {\n\t\t\tmeta[i].length = v.Len()\n\t\t\tmeta[i].v = v\n\n\t\t\tanySlices = true\n\t\t\tflatArgsCount += meta[i].length\n\n\t\t\tif meta[i].length == 0 {\n\t\t\t\treturn \"\", nil, errors.New(\"empty slice passed to 'in' query\")\n\t\t\t}\n\t\t} else {\n\t\t\tmeta[i].i = arg\n\t\t\tflatArgsCount++\n\t\t}\n\t}\n\n\t// don't do any parsing if there aren't any slices;  note that this means\n\t// some errors that we might have caught below will not be returned.\n\tif !anySlices {\n\t\treturn query, args, nil\n\t}\n\n\tnewArgs := make([]interface{}, 0, flatArgsCount)\n\n\tvar buf strings.Builder\n\tbuf.Grow(len(query) + len(\", ?\")*flatArgsCount)\n","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/jmoiron/sqlx/blob/41dac167fdad5e3fd81d66cafba0951dc6823a30/bind.go#L162-L198","documentation":"sqlx.In() builds an 'IN (...)' query by expanding slice arguments into a list of bind vars. If any passed argument is a slice with zero elements, there are no placeholders to expand and the generated SQL would be syntactically invalid, so sqlx refuses to build the query with this error.","triggerScenarios":"Calling sqlx.In (or QueryInx/NamedQuery variants that route through it) with an empty slice among the variadic args, e.g. sqlx.In(\"SELECT * FROM t WHERE id IN (?)\", ids) where len(ids)==0. The check fires in the bind.go meta-building loop when meta[i].length==0.","commonSituations":"Filtering by a user-selected list that turned out empty (no checkboxes selected, no results from a previous query feeding an IN clause). Very common in list/filter endpoints where the filter collection starts empty.","solutions":["Short-circuit before calling In: if len(slice)==0, skip the query or return an empty result set","Construct the query differently for the empty case (e.g. query with a guaranteed-false predicate like \"WHERE 1=0\")","Drop the IN clause entirely when the slice is empty","Use Go's slices/len validation in a helper wrapper around sqlx.In"],"exampleFix":"// before\nquery, args, err := sqlx.In(\"SELECT * FROM users WHERE id IN (?)\", ids)\n// after\nif len(ids) == 0 {\n    return nil, nil // or \"SELECT * FROM users WHERE 1=0\"\n}\nquery, args, err := sqlx.In(\"SELECT * FROM users WHERE id IN (?)\", ids)","handlingStrategy":"validation","validationCode":"func safeIn(query string, args ...interface{}) (string, []interface{}, error) {\n    for _, a := range args {\n        if rv := reflect.ValueOf(a); rv.Kind() == reflect.Slice && rv.Len() == 0 {\n            return \"\", nil, fmt.Errorf(\"empty slice for query %q\", query)\n        }\n    }\n    return sqlx.In(query, args...)\n}","typeGuard":"func isEmptySliceArg(a interface{}) bool {\n    if a == nil { return false }\n    v := reflect.ValueOf(a)\n    return v.Kind() == reflect.Slice && v.Len() == 0\n}","tryCatchPattern":"query, args, err := sqlx.In(\"SELECT * FROM t WHERE id IN (?)\", ids)\nif err != nil {\n    if strings.Contains(err.Error(), \"empty slice passed to 'in' query\") {\n        return nil, nil // empty result is a valid outcome\n    }\n    return nil, err\n}","preventionTips":["Always check len(slice) before building IN queries","Route IN-query construction through a wrapper that handles the empty case","Return empty results instead of querying when the filter list is empty"],"tags":["go","sqlx","query-building","empty-input"],"backgroundTag":"empty-slice-in-query","analyzedSha":"41dac167fdad5e3fd81d66cafba0951dc6823a30","analyzedAt":"2026-09-03T06:10:20.382Z","contentChangedAt":"2026-09-03T06:10:20.382Z","schemaVersion":2},"datasetVersion":"2026-09-10T12:17:11.382Z"}