{"record":{"id":"ed4ca011f3c16cbf","repo":"MHSanaei/3x-ui","slug":"tg-id-must-be-a-positive-integer","errorCode":null,"errorMessage":"tg_id must be a positive integer","messagePattern":"tg_id must be a positive integer","errorType":"validation","errorClass":null,"httpStatus":200,"severity":"warning","filePath":"internal/web/service/client_lookup.go","lineNumber":109,"sourceCode":"func (s *ClientService) GetInboundIdsForEmail(tx *gorm.DB, email string) ([]int, error) {\n\tif tx == nil {\n\t\ttx = database.GetDB()\n\t}\n\tvar ids []int\n\terr := tx.Table(\"client_inbounds\").\n\t\tSelect(\"client_inbounds.inbound_id\").\n\t\tJoins(\"JOIN clients ON clients.id = client_inbounds.client_id\").\n\t\tWhere(\"clients.email = ?\", email).\n\t\tScan(&ids).Error\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn ids, nil\n}\n\nfunc (s *ClientService) GetRecordsByTgID(tgId int64) ([]*model.ClientRecord, error) {\n\tif tgId <= 0 {\n\t\treturn nil, errors.New(\"tg_id must be a positive integer\")\n\t}\n\tvar rows []*model.ClientRecord\n\terr := database.GetDB().Where(\"tg_id = ?\", tgId).Find(&rows).Error\n\treturn rows, err\n}\n\nfunc (s *ClientService) GetByID(id int) (*model.ClientRecord, error) {\n\trow := &model.ClientRecord{}\n\tif err := database.GetDB().Where(\"id = ?\", id).First(row).Error; err != nil {\n\t\treturn nil, err\n\t}\n\treturn row, nil\n}\n\nfunc (s *ClientService) GetInboundIdsForRecord(id int) ([]int, error) {\n\tvar ids []int\n\terr := database.GetDB().Table(\"client_inbounds\").\n\t\tWhere(\"client_id = ?\", id).","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/service/client_lookup.go#L91-L127","documentation":"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.","triggerScenarios":"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).","commonSituations":"Code paths doing tgId, _ := strconv.ParseInt(...) and proceeding on failure; API handlers defaulting to 0.","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"],"exampleFix":"// before\ntgId, _ := strconv.ParseInt(raw, 10, 64)\nrows, err := svc.GetRecordsByTgID(tgId)\n\n// after\ntgId, err := strconv.ParseInt(raw, 10, 64)\nif err != nil || tgId <= 0 {\n    return fmt.Errorf(\"invalid telegram id: %q\", raw)\n}\nrows, err := svc.GetRecordsByTgID(tgId)","handlingStrategy":"validation","validationCode":"tgId, err := strconv.ParseInt(raw, 10, 64)\nif err != nil || tgId <= 0 {\n    return nil, fmt.Errorf(\"invalid telegram id %q\", raw)\n}","typeGuard":null,"tryCatchPattern":"rows, err := svc.GetRecordsByTgID(tgId)\nif err != nil {\n    if strings.Contains(err.Error(), \"positive integer\") {\n        // input problem: reject the request, do not retry\n    }\n    return err\n}","preventionTips":["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"],"tags":["validation","telegram","database","api"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}