{"record":{"id":"135f6b4010f02af7","repo":"gastownhall/beads","slug":"no-linear-client","errorCode":null,"errorMessage":"no linear client","messagePattern":"no linear client","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/linear/mapping.go","lineNumber":485,"sourceCode":"\tcase types.StatusBlocked:\n\t\treturn \"started\" // Linear doesn't have blocked state type\n\tcase types.StatusClosed:\n\t\treturn \"completed\"\n\tdefault:\n\t\treturn \"unstarted\"\n\t}\n}\n\n// LabelCache maps normalized Linear label names (lowercase) to Linear label IDs\n// for a single team.\ntype LabelCache struct {\n\tIDByLowerName map[string]string\n}\n\n// BuildLabelCache fetches team labels and indexes them by lowercase trimmed name.\nfunc BuildLabelCache(ctx context.Context, client *Client) (*LabelCache, error) {\n\tif client == nil {\n\t\treturn nil, fmt.Errorf(\"no linear client\")\n\t}\n\tlabels, err := client.GetTeamLabels(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tc := &LabelCache{\n\t\tIDByLowerName: make(map[string]string, len(labels)),\n\t}\n\tfor _, lb := range labels {\n\t\tk := strings.ToLower(strings.TrimSpace(lb.Name))\n\t\tif k != \"\" && lb.ID != \"\" {\n\t\t\tc.IDByLowerName[k] = lb.ID\n\t\t}\n\t}\n\treturn c, nil\n}\n\n// IssueTypeToLinearLabelLookupKey returns the label_type_map key (lowercase) for","sourceCodeStart":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/linear/mapping.go#L467-L503","documentation":"BuildLabelCache requires a non-nil *Client to call GetTeamLabels. This guard error fires immediately when a nil client is passed, before any network call is made. It indicates a wiring/initialization bug in the caller, not a Linear API problem.","triggerScenarios":"Calling linear.BuildLabelCache(ctx, nil), typically because an enclosing struct's client field was never initialized or a factory returned nil without error propagation.","commonSituations":"Lazy client construction skipped when config load partially failed; a *Client variable left nil on an error path that returned nil, nil; tests constructing mapping helpers without a stub client.","solutions":["Initialize the Linear client before calling BuildLabelCache (e.g. linear.NewClient(token)) and check its constructor error.","Add a nil check on the client at the call site (CreateIssue/UpdateIssue/BatchPush) and fail fast with a clear config error.","Fix any constructor path that can return (nil, nil) so callers never hold a nil client.","In tests, pass a stubbed *Client or test the cache-building logic via an interface."],"exampleFix":"// before\ncache, err := linear.BuildLabelCache(ctx, client) // client is nil\n// after\nif client == nil {\n    return fmt.Errorf(\"linear client not initialized; check config/token loading\")\n}\ncache, err := linear.BuildLabelCache(ctx, client)","handlingStrategy":"validation","validationCode":"if client == nil {\n    return fmt.Errorf(\"linear client not initialized\")\n}\ncache, err := linear.BuildLabelCache(ctx, client)","typeGuard":"func hasLinearClient(c *linear.Client) bool { return c != nil }","tryCatchPattern":null,"preventionTips":["Construct the Linear client once at startup and fail fast if its constructor errors.","Never return (nil, nil) from client factory functions.","Add a unit test asserting BuildLabelCache is only reachable with a non-nil client."],"tags":["linear","nil-pointer","initialization","go"],"backgroundTag":"nil-client-guard","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}