MHSanaei/3x-ui · warning
tg_id must be a positive integer
Error message
tg_id must be a positive integer
What it means
GetRecordsByTgID validates that the Telegram ID argument is a positive (>0) int64 before querying client_records by tg_id. Zero and negatives are rejected because tg_id=0 would match every record that has no linked Telegram account, returning a meaningless result set; negative IDs never exist in Telegram. Callers parsing user input should treat this as a validation failure, not a DB error.
Source
Thrown at internal/web/service/client_lookup.go:109
func (s *ClientService) GetInboundIdsForEmail(tx *gorm.DB, email string) ([]int, error) {
if tx == nil {
tx = database.GetDB()
}
var ids []int
err := tx.Table("client_inbounds").
Select("client_inbounds.inbound_id").
Joins("JOIN clients ON clients.id = client_inbounds.client_id").
Where("clients.email = ?", email).
Scan(&ids).Error
if err != nil {
return nil, err
}
return ids, nil
}
func (s *ClientService) GetRecordsByTgID(tgId int64) ([]*model.ClientRecord, error) {
if tgId <= 0 {
return nil, errors.New("tg_id must be a positive integer")
}
var rows []*model.ClientRecord
err := database.GetDB().Where("tg_id = ?", tgId).Find(&rows).Error
return rows, err
}
func (s *ClientService) GetByID(id int) (*model.ClientRecord, error) {
row := &model.ClientRecord{}
if err := database.GetDB().Where("id = ?", id).First(row).Error; err != nil {
return nil, err
}
return row, nil
}
func (s *ClientService) GetInboundIdsForRecord(id int) ([]int, error) {
var ids []int
err := database.GetDB().Table("client_inbounds").
Where("client_id = ?", id).View on GitHub (pinned to ad32144c42)
Solutions
- Check the parse error before calling: if err := ...; err != nil or value <= 0, return 'invalid tg_id' to the caller
- Default to a not-found response rather than 0 when the parameter is absent
- For 'unassigned' queries, use a dedicated IsNull/'tg_id IS NULL' query instead of tg_id=0
Example fix
// before
tgId, _ := strconv.ParseInt(raw, 10, 64)
rows, err := svc.GetRecordsByTgID(tgId)
// after
tgId, err := strconv.ParseInt(raw, 10, 64)
if err != nil || tgId <= 0 {
return fmt.Errorf("invalid telegram id: %q", raw)
}
rows, err := svc.GetRecordsByTgID(tgId) Defensive patterns
Strategy: validation
Validate before calling
tgId, err := strconv.ParseInt(raw, 10, 64)
if err != nil || tgId <= 0 {
return nil, fmt.Errorf("invalid telegram id %q", raw)
} Try / catch
rows, err := svc.GetRecordsByTgID(tgId)
if err != nil {
if strings.Contains(err.Error(), "positive integer") {
// input problem: reject the request, do not retry
}
return err
} Prevention
- Never discard the strconv error with _ when the value feeds a query
- Treat absent tg_id parameters as 'not found', not 0
- Use tg_id IS NULL queries for unassigned records
When it happens
Trigger: Calling GetRecordsByTgID(0) when input parsing failed and the error was ignored (the strconv result is often discarded); passing -1 from a misparsed unsigned value; looking up records before any client has that tg_id linked (0 used as 'missing' sentinel).
Common situations: Code paths doing tgId, _ := strconv.ParseInt(...) and proceeding on failure; API handlers defaulting to 0.
Related errors
- The new username and password are empty
- telegram bot disabled
- ❌ Failed to get inbounds.
- token not found
- not a 3x-ui panel database: required table %q is missing
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/ed4ca011f3c16cbf.
Report an issue: GitHub.