{"record":{"id":"0e3206c57eb3c865","repo":"netbirdio/netbird","slug":"group-not-found","errorCode":null,"errorMessage":"group not found","messagePattern":"group not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"shared/management/client/rest/groups.go","lineNumber":13,"sourceCode":"package rest\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\n\t\"github.com/netbirdio/netbird/shared/management/http/api\"\n)\n\n// ErrGroupNotFound is returned when a group is not found\nvar ErrGroupNotFound = errors.New(\"group not found\")\n\n// GroupsAPI APIs for Groups, do not use directly\ntype GroupsAPI struct {\n\tc *Client\n}\n\n// List list all groups\n// See more: https://docs.netbird.io/api/resources/groups#list-all-groups\nfunc (a *GroupsAPI) List(ctx context.Context) ([]api.Group, error) {\n\tresp, err := a.c.NewRequest(ctx, \"GET\", \"/api/groups\", nil, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif resp.Body != nil {\n\t\tdefer resp.Body.Close()\n\t}\n\tret, err := parseResponse[[]api.Group](resp)\n\treturn ret, err","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/shared/management/client/rest/groups.go#L1-L31","documentation":"Sentinel error returned by GroupsAPI.GetByName when the management REST API's group list, filtered by the name query parameter, comes back with zero entries. It means no group with that exact name exists in the account the API token belongs to. Matching is exact, so typos, case differences, and names owned by another account all produce it.","triggerScenarios":"rest.Groups.GetByName(ctx, name) where name is misspelled, has different case or whitespace, was deleted or renamed concurrently, or exists only in a different account than the token's.","commonSituations":"Automation that attaches peers to a group before creating it; service-user token scoped to the wrong account; group names read from stale config after a rename.","solutions":["List all groups (Groups.List) and compare the exact name, case-sensitively","Create the group first with Groups.Create, or fix the name in the calling config","Confirm the API token belongs to the account that owns the group"],"exampleFix":"// before\ngroup, err := restClient.Groups.GetByName(ctx, \"my-group\")\n\n// after\ngroup, err := restClient.Groups.GetByName(ctx, \"my-group\")\nif errors.Is(err, rest.ErrGroupNotFound) {\n\tgroup, err = restClient.Groups.Create(ctx, api.PostApiGroupsJSONRequestBody{Name: \"my-group\"})\n\tif err != nil {\n\t\treturn err\n\t}\n}","handlingStrategy":"try-catch","validationCode":"groups, err := restClient.Groups.List(ctx)\nif err != nil {\n\treturn err\n}\nvar found *api.Group\nfor i := range groups {\n\tif groups[i].Name != nil && *groups[i].Name == wantName {\n\t\tfound = &groups[i]\n\t\tbreak\n\t}\n}","typeGuard":"func isGroupNotFound(err error) bool {\n\treturn errors.Is(err, rest.ErrGroupNotFound)\n}","tryCatchPattern":"group, err := restClient.Groups.GetByName(ctx, name)\nif errors.Is(err, rest.ErrGroupNotFound) {\n\t// create it or fall back to a configured group ID\n} else if err != nil {\n\treturn err\n}","preventionTips":["Compare against the sentinel with errors.Is, never string matching","Resolve group names once at startup and cache the ID","Create groups before referencing them in automation"],"tags":["rest","groups","api","not-found"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}