#7835·gorm

CreateInBatches silently skips uint64 ID population above MaxInt64

Author: CreedowlCreated Aug 5, 2026Updated Aug 5, 2026
Labelstype:with reproduction steps

GORM Playground Link

https://github.com/go-gorm/playground/pull/857

Description

CreateInBatches silently skips primary-key population when MySQL generates a BIGINT UNSIGNED auto-increment ID greater than math.MaxInt64.

The database insert succeeds, RowsAffected is 1, and GORM returns no error, but the model's uint64 primary key remains 0.

Environment

  • GORM: current master (1d6ce99528060be18a42be09aca8d39efcb47f28)
  • MySQL driver: github.com/go-sql-driver/mysql v1.9.3
  • MySQL: 8.0.32
  • Go: 1.25.5

Reproduction

Create an unsigned auto-increment table starting at 2^63:

sql
CREATE TABLE unsigned_auto_increment_records (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    name VARCHAR(32) NOT NULL,
    PRIMARY KEY (id)
) AUTO_INCREMENT = 9223372036854775808;

Insert a model with a uint64 primary key:

go
type unsignedAutoIncrementRecord struct {
    ID   uint64 `gorm:"primaryKey;autoIncrement"`
    Name string
}

record := &unsignedAutoIncrementRecord{Name: "test"}
result := DB.Table("unsigned_auto_increment_records").
    CreateInBatches([]*unsignedAutoIncrementRecord{record}, 100)

The Playground test verifies the persisted value separately using CAST(id AS CHAR).

Actual behavior

result.Error:        <nil>
result.RowsAffected: 1
persisted database ID: 9223372036854775808
record.ID:             0

The failing assertion is:

database inserted ID 9223372036854775808, but GORM populated ID 0

Expected behavior

GORM should either:

  1. populate the uint64 primary key correctly through a uint64-safe mechanism, or
  2. return an explicit error explaining that the generated ID cannot be represented by database/sql.Result.LastInsertId().

It should not report a successful create while silently leaving the generated primary key at zero.

Suspected cause

database/sql.Result.LastInsertId() returns int64. For an unsigned MySQL ID greater than math.MaxInt64, the MySQL driver returns the bit pattern as a negative int64 with a nil error.

GORM currently checks:

go
insertID, err := result.LastInsertId()
insertOk := err == nil && insertID > 0
if !insertOk {
    db.AddError(err)
    return
}

Because insertID is negative while err is nil, GORM skips population and adds no error. The underlying database/sql limitation is known (go-sql-driver/mysql#738), but GORM can at least avoid treating this state as a fully successful create.