jmoiron/sqlx · error
length of array is 0: %#v
Error message
length of array is 0: %#v
What it means
When binding an array/slice argument with the array-style bind type (e.g. Postgres' expanded ?* binding), bindArray needs at least one element to expand parameters for. A zero-length array yields no parameter groups, which would produce an invalid/empty IN clause, so sqlx errors out instead of emitting broken SQL.
Source
Thrown at named.go:283
buffer.WriteString(bound[openingBracketIndex:closingBracketIndex])
}
buffer.WriteString(bound[closingBracketIndex:])
return buffer.String()
}
// bindArray binds a named parameter query with fields from an array or slice of
// structs argument.
func bindArray(bindType int, query string, arg interface{}, m *reflectx.Mapper) (string, []interface{}, error) {
// do the initial binding with QUESTION; if bindType is not question,
// we can rebind it at the end.
bound, names, err := compileNamedQuery([]byte(query), QUESTION)
if err != nil {
return "", []interface{}{}, err
}
arrayValue := reflect.ValueOf(arg)
arrayLen := arrayValue.Len()
if arrayLen == 0 {
return "", []interface{}{}, fmt.Errorf("length of array is 0: %#v", arg)
}
var arglist = make([]interface{}, 0, len(names)*arrayLen)
for i := 0; i < arrayLen; i++ {
elemArglist, err := bindAnyArgs(names, arrayValue.Index(i).Interface(), m)
if err != nil {
return "", []interface{}{}, err
}
arglist = append(arglist, elemArglist...)
}
if arrayLen > 1 {
bound = fixBound(bound, arrayLen)
}
// adjust binding type if we weren't on question
if bindType != QUESTION {
bound = Rebind(bindType, bound)
}
return bound, arglist, nil
}View on GitHub (pinned to 41dac167fd)
Solutions
- Guard for empty slices before binding and return an empty result or use a query variant without the IN clause.
- If SQL semantics allow, use a sentinel value (e.g. WHERE (:ids IS NULL) patterns) or `= ANY($1)` with pq.Array.
- Ensure the slice is populated before calling the named API.
- Handle the error and skip executing the query when there is nothing to bind.
Example fix
// before
var ids []int64
rows, _ := db.NamedQuery("SELECT * FROM t WHERE id IN (:ids)", map[string]interface{}{"ids": ids})
// after
if len(ids) == 0 {
return nil, nil // or use always-false query
}
rows, _ := db.NamedQuery("SELECT * FROM t WHERE id IN (:ids)", map[string]interface{}{"ids": ids}) Defensive patterns
Strategy: validation
Validate before calling
if len(ids) == 0 {
return nil, nil // skip the IN-clause query entirely
} Try / catch
q, args, err := db.BindNamed(query, arg)
if err != nil && strings.Contains(err.Error(), "length of array is 0") {
// empty input: return empty result instead of executing
return nil, err
} Prevention
- Early-return on empty slices before building IN queries.
- Use SQL that tolerates empty sets (e.g. = ANY(array) with drivers that accept it).
- Never feed nil/empty slices into array-expanding bind types.
- Add a guard helper like inClause(items) that returns a known-empty result.
When it happens
Trigger: Binding a slice/array via BindNamed/Named-style APIs where the mapped bind type expands arrays (e.g. BindType returns Question for slices?) and the slice has len==0 — e.g. NamedExec with an empty slice for an IN clause.
Common situations: SELECT ... IN (:ids) with ids from an empty filter result; slice nil/empty because an earlier query returned nothing; passing an empty array-typed struct field.
Related errors
- could not find name %s in %#v
- sqlx.bindNamedMapper: unsupported map type: %T
- unexpected `:` while reading named param at
- argument not a struct
- missing field
AI-assisted analysis of jmoiron/sqlx@41dac167fd (2026-09-03).
Data as JSON: /api/errors/7a9aff63ebec05f5.
Report an issue: GitHub.