From 16b2bcf9aa8ce20c5c2b66ec055cd19ddc262110 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 18 Jul 2026 13:06:05 +0200 Subject: [PATCH] fix(database): repair legacy string tgId in inbound settings on upgrade Old panel builds and external tools writing directly to the DB store tgId as a JSON string; parsing such settings into the strict int64 Client model fails with "json: cannot unmarshal string into Go struct field Client.tgId of type int64" and blocks every client operation on that inbound. The one-shot InboundClientTgIdFix seeder already ran on existing installs, so the repair is re-registered as InboundClientTgIdFix2 to run once more on upgrade, and it now preserves numeric string ids instead of zeroing them. The Client model itself stays number-only. --- internal/database/db.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/internal/database/db.go b/internal/database/db.go index 9738faafc..faab8f95b 100644 --- a/internal/database/db.go +++ b/internal/database/db.go @@ -1057,7 +1057,7 @@ func runSeeders(isUsersEmpty bool) error { } if empty && isUsersEmpty { - seeders := []string{"UserPasswordHash", "ClientsTable", "InboundClientsArrayFix", "InboundClientTgIdFix", "InboundClientSubIdFix", "FreedomFinalRulesReverseFix", "ApiTokensHash", "LegacyProxySettingsCleanup", "WireguardPeersToClients", "MtprotoSecretsToClients", "NodeInboundsAdopted", "ResetIpLimitNoFail2ban"} + seeders := []string{"UserPasswordHash", "ClientsTable", "InboundClientsArrayFix", "InboundClientTgIdFix2", "InboundClientSubIdFix", "FreedomFinalRulesReverseFix", "ApiTokensHash", "LegacyProxySettingsCleanup", "WireguardPeersToClients", "MtprotoSecretsToClients", "NodeInboundsAdopted", "ResetIpLimitNoFail2ban"} for _, name := range seeders { if err := db.Create(&model.HistoryOfSeeders{SeederName: name}).Error; err != nil { return err @@ -1126,7 +1126,7 @@ func runSeeders(isUsersEmpty bool) error { } } - if !slices.Contains(seedersHistory, "InboundClientTgIdFix") { + if !slices.Contains(seedersHistory, "InboundClientTgIdFix2") { if err := normalizeInboundClientTgId(); err != nil { return err } @@ -1384,6 +1384,11 @@ func normalizeInboundClientTgId() error { continue } obj["tgId"] = int64(0) + if s, isStr := tgRaw.(string); isStr { + if id, err := strconv.ParseInt(strings.ReplaceAll(strings.TrimSpace(s), " ", ""), 10, 64); err == nil { + obj["tgId"] = id + } + } clients[i] = obj mutated = true } @@ -1401,7 +1406,7 @@ func normalizeInboundClientTgId() error { return err } } - return tx.Create(&model.HistoryOfSeeders{SeederName: "InboundClientTgIdFix"}).Error + return tx.Create(&model.HistoryOfSeeders{SeederName: "InboundClientTgIdFix2"}).Error }) }