kataras/iris · error

sqlx: bind: table: %q: unexpected destination kind: %q

Error message

sqlx: bind: table: %q: unexpected destination kind: %q

What it means

Bind maps query results into a destination via reflection and supports only specific destination kinds (pointer-to-struct, pointer-to-slice-of-struct, and similar scan targets). Passing a dst whose reflected kind falls outside the switch's handled cases hits the default branch and returns this error. It is a programmer-API misuse, not a data problem.

Source

Thrown at x/sqlx/sqlx.go:175

		return src.Err()
	case reflect.Slice:
		for src.Next() {
			elem := reflect.New(typ).Elem()
			if err = r.bindSingle(typ, elem, columnTypes, src); err != nil {
				return err
			}

			val = reflect.Append(val, elem)
		}

		if err = src.Err(); err != nil {
			return err
		}

		reflect.ValueOf(dst).Elem().Set(val)
		return nil
	default:
		return fmt.Errorf("sqlx: bind: table: %q: unexpected destination kind: %q", r.Name, typ.Kind().String())
	}
}

func (r *Row) bindSingle(typ reflect.Type, val reflect.Value, columnTypes []*sql.ColumnType, scanner interface{ Scan(...any) error }) error {
	fieldPtrs, err := r.lookupStructFieldPtrs(typ, val, columnTypes)
	if err != nil {
		return fmt.Errorf("sqlx: bind: table: %q: %w", r.Name, err)
	}

	return scanner.Scan(fieldPtrs...)
}

func (r *Row) lookupStructFieldPtrs(typ reflect.Type, val reflect.Value, columnTypes []*sql.ColumnType) ([]any, error) {
	fieldPtrs := make([]any, 0, len(columnTypes))

	for _, columnType := range columnTypes {
		columnName := columnType.Name()
		tableColumn, ok := r.Columns[columnName]

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Pass a *Struct or *[]Struct as dst
  2. Dereference double pointers before calling
  3. Check that dst is not nil
  4. If scanning a scalar, use the raw database/sql Rows.Scan instead of Bind

Example fix

// before
var user *User
err := db.Query(row, &user, "SELECT ...")
// after
var user User
err := db.Query(row, &user, "SELECT ...")
Defensive patterns

Strategy: type-guard

Validate before calling

if dst == nil || reflect.TypeOf(dst).Kind() != reflect.Ptr { return errors.New("dst must be a pointer to struct or slice") }

Type guard

func isBindableDst(dst any) bool {
	t := reflect.TypeOf(dst)
	if t == nil || t.Kind() != reflect.Ptr { return false }
	e := t.Elem()
	return e.Kind() == reflect.Struct || e.Kind() == reflect.Slice
}

Try / catch

if err := db.Query(row, dst, q); err != nil { if strings.Contains(err.Error(), "unexpected destination kind") { return fmt.Errorf("bad dst %T: %w", dst, err) } return err }

Prevention

When it happens

Trigger: Passing a non-pointer, a pointer to a map, a pointer to a primitive (e.g. *int where a struct/slice is expected), or a **struct (double pointer) as dst to Query/Bind.

Common situations: Copying code from database/sql style scans into sqlx Bind; accidentally passing &userSlice where userSlice is already a pointer; passing nil interface.

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/909bce93fbf48122. Report an issue: GitHub.