{"record":{"id":"0a9abdf39849ed3c","repo":"vxcontrol/pentagi","slug":"errsearchlogsinvalidrequest","errorCode":"ErrSearchlogsInvalidRequest","errorMessage":"group field not found","messagePattern":"group field not found","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"backend/pkg/server/services/searchlogs.go","lineNumber":101,"sourceCode":"\t\t}\n\t} else if slices.Contains(privs, \"searchlogs.view\") {\n\t\tscope = func(db *gorm.DB) *gorm.DB {\n\t\t\treturn db.\n\t\t\t\tJoins(\"INNER JOIN flows f ON f.id = flow_id\").\n\t\t\t\tWhere(\"f.user_id = ?\", uid)\n\t\t}\n\t} else {\n\t\tlogger.FromContext(c).Errorf(\"error filtering user role permissions: permission not found\")\n\t\tresponse.Error(c, response.ErrNotPermitted, nil)\n\t\treturn\n\t}\n\n\tquery.Init(\"searchlogs\", searchlogsSQLMappers)\n\n\tif query.Group != \"\" {\n\t\tif _, ok := searchlogsSQLMappers[query.Group]; !ok {\n\t\t\tlogger.FromContext(c).Errorf(\"error finding searchlogs grouped: group field not found\")\n\t\t\tresponse.Error(c, response.ErrSearchlogsInvalidRequest, errors.New(\"group field not found\"))\n\t\t\treturn\n\t\t}\n\n\t\tvar respGrouped searchlogsGrouped\n\t\tif respGrouped.Total, err = query.QueryGrouped(s.db, &respGrouped.Grouped, scope); err != nil {\n\t\t\tlogger.FromContext(c).WithError(err).Errorf(\"error finding searchlogs grouped\")\n\t\t\tresponse.Error(c, response.ErrInternal, err)\n\t\t\treturn\n\t\t}\n\n\t\tresponse.Success(c, http.StatusOK, respGrouped)\n\t\treturn\n\t}\n\n\tif resp.Total, err = query.Query(s.db, &resp.SearchLogs, scope); err != nil {\n\t\tlogger.FromContext(c).WithError(err).Errorf(\"error finding searchlogs\")\n\t\tresponse.Error(c, response.ErrInternal, err)\n\t\treturn","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/services/searchlogs.go#L83-L119","documentation":"GetSearchlogs supports grouped aggregation of search logs. The `group` query parameter is validated against searchlogsSQLMappers; any value not present in that map is rejected with ErrSearchlogsInvalidRequest before the grouped SQL query executes.","triggerScenarios":"GET /searchlogs?group=<field> where <field> is not a key of searchlogsSQLMappers, e.g. grouping by 'engine' when only certain columns are mapped, or any misspelled/unmapped name.","commonSituations":"Analytics UIs letting users pick arbitrary columns to group by; API clients hardcoding a field name from an older backend version; copying group parameters between searchlogs and other entities whose mappers differ.","solutions":["Pick a group value that exists in searchlogsSQLMappers in backend/pkg/server/services/searchlogs.go.","Drop the group parameter for a flat (non-grouped) listing.","If grouping by engine/another unmapped column is needed, extend searchlogsSQLMappers and redeploy.","Constrain the UI's group dropdown to the documented groupable fields."],"exampleFix":"// before\nGET /api/v1/searchlogs?group=Engine\n// after\nGET /api/v1/searchlogs?group=engine","handlingStrategy":"validation","validationCode":"const SEARCHLOGS_GROUP_FIELDS = ['engine', 'created_at']; // keys of searchlogsSQLMappers\nif (group && !SEARCHLOGS_GROUP_FIELDS.includes(group)) {\n  throw new Error(`invalid group field for searchlogs: ${group}`);\n}","typeGuard":"function isValidSearchlogGroup(g) {\n  return typeof g === 'string' && SEARCHLOGS_GROUP_FIELDS.includes(g);\n}","tryCatchPattern":"try {\n  return await api.getSearchlogs({ group });\n} catch (e) {\n  if (e.code === 'ErrSearchlogsInvalidRequest' && e.message === 'group field not found') {\n    return await api.getSearchlogs({});\n  }\n  throw e;\n}","preventionTips":["Constrain analytics group-by dropdowns to fields in searchlogsSQLMappers.","Validate the group parameter before the request.","Keep client constants updated when backend mappers change.","Retry ungrouped when this specific 400 is returned."],"tags":["rest-api","validation","query-params","http-400"],"backgroundTag":"invalid-group-field","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}