Small tool on database/sql returned half a list. No error. The code.
func names(ctx context.Context, db *sql.DB) ([]string, error) {
rows, err := db.QueryContext(ctx, `SELECT name FROM users ORDER BY id`)
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
if err != nil {
return nil, fmt.Errorf("users: %w", err)
}
defer rows.Close()
var out []string
for rows.Next() {
var n string
if err := rows.Scan(&n); err != nil {
return nil, fmt.Errorf("scan: %w", err)
}
out = append(out, n)
}
return out, nil
}
Context with a deadline. The deadline fired in the middle of the fetch, rows.Next() returned false, the loop ended, and the function handed back what it had collected plus nil. The error was sitting in rows.Err() and nothing asked for it.
Fix is two lines after the loop, if err := rows.Err(); err != nil and a return with %w. Done. Now hunting for the other loops like it.