{"record":{"id":"e4dfa98815ab7f12","repo":"crowdsecurity/crowdsec","slug":"invalid-id-gt-value-w-w","errorCode":null,"errorMessage":"invalid id_gt value: %w: %w","messagePattern":"invalid id_gt value: %w: %w","errorType":"validation","errorClass":"InvalidFilter","httpStatus":null,"severity":"warning","filePath":"pkg/database/decisionfilter.go","lineNumber":99,"sourceCode":"\t\t\t}\n\t\tcase \"limit\":\n\t\t\tlimit, err := strconv.Atoi(value[0])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid limit value: %w: %w\", err, InvalidFilter)\n\t\t\t}\n\n\t\t\tquery = query.Limit(limit)\n\t\tcase \"offset\":\n\t\t\toffset, err := strconv.Atoi(value[0])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid offset value: %w: %w\", err, InvalidFilter)\n\t\t\t}\n\n\t\t\tquery = query.Offset(offset)\n\t\tcase \"id_gt\":\n\t\t\tid, err := strconv.Atoi(value[0])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid id_gt value: %w: %w\", err, InvalidFilter)\n\t\t\t}\n\n\t\t\tquery = query.Where(decision.IDGT(id))\n\t\t}\n\t}\n\n\tquery, err = decisionIPFilter(query, contains, rng)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"fail to apply StartIpEndIpFilter: %w\", err)\n\t}\n\n\treturn query, nil\n}\n\nfunc decisionIPv4Filter(decisions *ent.DecisionQuery, contains bool, rng csnet.Range) (*ent.DecisionQuery, error) {\n\tif contains {\n\t\t// Decision contains {start_ip,end_ip}\n\t\treturn decisions.Where(decision.And(","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/decisionfilter.go#L81-L117","documentation":"applyDecisionFilter rejects the request because the 'id_gt' (id greater-than) query parameter is not a valid integer (strconv.Atoi fails). This filter is used for keyset-style pagination of decisions; wrapped with the InvalidFilter sentinel.","triggerScenarios":"GET /v1/decisions?id_gt=last or ?id_gt=0.5 on decisions endpoints; also negative values will parse but may be unexpected.","commonSituations":"Clients tracking 'last seen id' whose stored value got corrupted or truncated; passing a decision UUID instead of the numeric ID.","solutions":["Send the numeric decision ID as an integer (e.g. ?id_gt=12345).","Use the numeric 'id' field from the previous page's last decision, not its UUID.","Omit id_gt when not using keyset pagination.","Cast/validate the stored last-id to int before constructing the query."],"exampleFix":"// before\nGET /v1/decisions?id_gt=abc-uuid-123\n// after\nGET /v1/decisions?id_gt=12345","handlingStrategy":"validation","validationCode":"lastID, err := strconv.Atoi(storedLastID)\nif err != nil {\n    return fmt.Errorf(\"corrupt cursor %q: %w\", storedLastID, err)\n}\n// then pass lastID as id_gt","typeGuard":null,"tryCatchPattern":"resp, err := lapi.GetDecisions(ctx, models.GetDecisionsOpts{IDGt: &lastID})\nif err != nil && strings.Contains(err.Error(), \"invalid id_gt value\") {\n    return fmt.Errorf(\"reset pagination cursor, %q is not an int\", storedLastID)\n}","preventionTips":["Store the numeric decision ID, not the UUID, for keyset pagination","Validate the cursor on load, reset on corruption","Persist cursors as integers in typed storage","Handle first-page case by omitting id_gt"],"tags":["api","query-parameter","pagination","validation"],"backgroundTag":"invalid-query-parameter","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}