Skip to content

fix: handle uint64 primary key ID overflowing MaxInt64 (#7835) - #7882

Open
Asthenia0412 wants to merge 3 commits into
go-gorm:masterfrom
Asthenia0412:fix/uint64-id-above-maxint64
Open

Asthenia0412 wants to merge 3 commits into
go-gorm:masterfrom
Asthenia0412:fix/uint64-id-above-maxint64

Conversation

@Asthenia0412

Copy link
Copy Markdown

Summary

Fixes silent failure of primary key population when MySQL BIGINT UNSIGNED auto-increment counter exceeds math.MaxInt64.

Root Cause

database/sql Result.LastInsertId returns int64. When DB value exceeds MaxInt64:

  • actual uint64: 9223372036854775808
  • as int64: -9223372036854775808 (overflow)

Original guard insertID > 0 rejected the overflowed negative value, returning early without populating the struct field.

Fix

In callbacks/create.go:

  • Signed primary keys: keep insertID > 0
  • Unsigned primary keys (uint/uint8/16/32/64): accept insertID != 0

Field.Set correctly converts the overflowed int64 back to uint64 via reflect.

Verification

  • go build ./... passes
  • go test ./... all pass

Fixes #7835.

…ches (go-gorm#7835)

database/sql Result.LastInsertId() returns (int64, error). When a MySQL
BIGINT UNSIGNED auto-increment counter exceeds math.MaxInt64 (e.g.
AUTO_INCREMENT = 9223372036854775808), the actual DB value overflows into
a negative int64, e.g.:

    actual uint64:  9223372036854775808
    as int64:      -9223372036854775808

The original validation used:

    insertOk := err == nil && insertID > 0

This treated the overflowed negative value as invalid and returned early,
leaving the struct's uint64 primary key at its zero value after insert.

This change keeps the original > 0 guard for signed primary keys, but
accepts any non-zero value for unsigned primary keys (uint8/16/32/64).
Field.Set correctly converts the overflowed int64 back to the true uint64
via Go's reflect assignment semantics.

Verification:
- go build ./... — passes
- go test ./... — all unit tests pass
- Confirmed Field.Set converts int64(-9223372036854775808) → uint64(9223372036854775808)

Fixes go-gorm#7835.

Signed-off-by: Asthenia0412 <33736553+Asthenia0412@users.noreply.github.com>
@Asthenia0412

Copy link
Copy Markdown
Author

Hello 👋

A quick note on the lint failure — this appears to be a CI infrastructure issue unrelated to this code change.

The failure message is:

could not import internal/goarch (-: could not load export data: ... export data version 5 is greater than maximum supported version 4)
could not import sync/atomic (-: same reason)

Local verification: using golangci-lint v2.13.2 (built with go1.27.0) on Go 1.25.1 (--new-from-rev origin/master): 0 issues.

I ran the full linter suite locally:

golangci-lint v2.13.0:  0 issues (--new-from-rev)
golangci-lint v2.13.2:  0 issues (--new-from-rev)  
golangci-lint v2.14.0:  0 issues (--new-from-rev)

All 26 database/matrix CI jobs pass. The lint typecheck error (export data v5 > v4) suggests the action is resolving v2.13 to a build whose bundled x/tools doesn't handle the current Go stable's export data format. This affects all open PRs currently — same error shows up on every lint run I've re-triggered.

This matches the same issue #7861 fixed in September by bumping to v2.13; it may need another bump (e.g. v2.14) or a Go version pin. Meanwhile the code is lint-clean per the configured linters. 🙏

@Asthenia0412
Asthenia0412 force-pushed the fix/uint64-id-above-maxint64 branch from 82ce779 to 7482b0d Compare October 13, 2026 02:33

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CreateInBatches silently skips uint64 ID population above MaxInt64

2 participants