vitessio/vitess · error
bad sql row
Error message
bad sql row
What it means
fakevtsql.ErrBadRow is returned by the fake driver's rows.Next when a configured row has a different number of values than the row's column count. It validates the fixture itself: test data must be rectangular relative to declared columns. It indicates a mistake in test setup, not in production code.
Source
Thrown at go/vt/vtadmin/vtsql/fakevtsql/rows.go:29
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fakevtsql
import (
"database/sql/driver"
"errors"
"fmt"
"io"
)
var (
// ErrBadRow is returned from Next() when a row has an incorrect number of
// fields.
ErrBadRow = errors.New("bad sql row")
// ErrRowsClosed is returned when attempting to operate on an already-closed
// Rows.
ErrRowsClosed = errors.New("err rows closed")
)
type rows struct {
cols []string
vals [][]any
pos int
closed bool
}
var _ driver.Rows = (*rows)(nil)
func (r *rows) Close() error {
r.closed = true
return nilView on GitHub (pinned to 01a25a7d17)
Solutions
- Fix the fixture so every row has exactly len(cols) values
- Verify each row's length in the test helper before handing it to the fake
- Regenerate the fixture after column changes
Example fix
// before
cols := []string{"id", "name"}
vals := [][]any{{1, "a"}, {2}} // short row
// after
vals := [][]any{{1, "a"}, {2, "b"}} Defensive patterns
Strategy: validation
Validate before calling
for i, row := range vals {
if len(row) != len(cols) {
t.Fatalf("fixture row %d has %d values, want %d", i, len(row), len(cols))
}
} Type guard
func isBadRow(err error) bool { return errors.Is(err, fakevtsql.ErrBadRow) } Try / catch
for rows.Next() {
if err := rows.Err(); errors.Is(err, fakevtsql.ErrBadRow) {
t.Fatalf("bad fixture row: %v", err)
}
} Prevention
- Validate fixture shape before registering rows with the fake
- Rebuild fixtures when columns change
- Use struct-to-row helpers so column counts stay in sync
When it happens
Trigger: Registering a rows fixture where some row slice has fewer or more entries than the column list passed to the fake; programmatically building rows where one branch appends fewer values.
Common situations: Hand-written test rows with a missing value after adding a column; building rows from variable-length data in test helpers.
Related errors
- use of closed connection
- unrecognized query
- err rows closed
- not allowed: deny-all security-policy enforced
- not allowed: read-only security-policy enforced
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/99f5b74ab6164c02.
Report an issue: GitHub.