gastownhall/beads · error
building state cache: no cache for primary team %s
Error message
building state cache: no cache for primary team %s
What it means
Returned by Tracker.BatchPush when no state cache exists for the primary team after the per-team build loop. This happens when the primary team's entry was skipped in the loop (nil team client) or absent from t.clients, so creates—which always target the primary team—cannot proceed.
Source
Thrown at internal/linear/tracker.go:312
// Build per-team state caches so that updates to issues belonging to different
// teams resolve workflow state IDs against the correct team's state list.
teamCaches := make(map[string]*StateCache, len(t.teamIDs))
for _, teamID := range t.teamIDs {
teamClient := t.clients[teamID]
if teamClient == nil {
continue
}
cache, err := BuildStateCache(ctx, teamClient)
if err != nil {
return nil, fmt.Errorf("building state cache for team %s: %w", teamID, err)
}
teamCaches[teamID] = cache
}
// The primary team's cache is used for creates, which always target the primary team.
primaryCache := teamCaches[t.teamIDs[0]]
if primaryCache == nil {
return nil, fmt.Errorf("building state cache: no cache for primary team %s", t.teamIDs[0])
}
teamLabelCaches := make(map[string]*LabelCache, len(t.teamIDs))
for _, teamID := range t.teamIDs {
teamClient := t.clients[teamID]
if teamClient == nil {
continue
}
lc, err := BuildLabelCache(ctx, teamClient)
if err != nil {
return nil, fmt.Errorf("building label cache for team %s: %w", teamID, err)
}
teamLabelCaches[teamID] = lc
}
primaryLabelCache := teamLabelCaches[t.teamIDs[0]]
if primaryLabelCache == nil {
return nil, fmt.Errorf("building label cache: no cache for primary team %s", t.teamIDs[0])
}View on GitHub (pinned to 71377f2769)
Solutions
- Ensure the primary team's Linear client is constructed successfully before BatchPush
- Check that teamIDs and the clients map are populated consistently (SetTeamIDs called before use)
- Verify credentials grant access to the primary team specifically
- Re-initialize the tracker; if in tests, register a fake client for the primary team
Example fix
// before
t.SetTeamIDs([]string{"ENG"}) // but t.clients["ENG"] never built
// after
t.Init(ctx, cfg) // builds clients for all teamIDs, including primary
if t.clients["ENG"] == nil { t.SkipLinear = true } Defensive patterns
Strategy: validation
Validate before calling
// Pre-check: primary team must have a live client before batch operations
primary := tracker.PrimaryTeamID()
if tracker.ClientForTeam(primary) == nil {
return fmt.Errorf("primary Linear team %s has no client; run Init first", primary)
} Try / catch
result, err := tracker.BatchPush(ctx, issues, forceIDs)
if err != nil && strings.Contains(err.Error(), "no cache for primary team") {
// re-initialize the tracker then retry once
if rerr := tracker.Init(ctx, cfg); rerr == nil {
result, err = tracker.BatchPush(ctx, issues, forceIDs)
}
} Prevention
- Always call Init (not just SetTeamIDs) before batch operations
- In tests, register a fake client for every team ID including the primary
- Assert t.clients covers teamIDs after initialization
- Treat client-build failures as fatal instead of silently skipping teams
When it happens
Trigger: BatchPush called where t.teamIDs[0] has a nil entry in t.clients (team configured by ID but its client construction failed or was skipped), leaving teamCaches[teamIDs[0]] unset.
Common situations: Partially initialized trackers in tests; config listing a primary team whose client failed to build (bad credentials scoped to another team); race or ordering issue where teamIDs was set after clients map was built.
Related errors
- building label cache: no cache for primary team %s
- no linear client
- Linear tracker not initialized
- no Linear client available
- building state cache for team %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/3196c6efc43c1ad5.
Report an issue: GitHub.