gastownhall/beads · error

building label cache: no cache for primary team %s

Error message

building label cache: no cache for primary team %s

What it means

Returned by Tracker.BatchPush when the primary team has no label cache after the build loop. Creates target the primary team and need its label cache to attach labels, so a missing cache fails the batch before any issue is pushed.

Source

Thrown at internal/linear/tracker.go:329

	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])
	}

	result := &tracker.BatchPushResult{}

	var toCreate []*types.Issue
	var toUpdate []*types.Issue

	for _, issue := range issues {
		extRef := ""
		if issue.ExternalRef != nil {
			extRef = *issue.ExternalRef
		}
		if extRef == "" || !IsLinearExternalRef(extRef) {
			toCreate = append(toCreate, issue)
		} else {
			toUpdate = append(toUpdate, issue)
		}
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Ensure the primary team's client exists before BatchPush (re-run Init/Validate)
  2. Keep teamIDs and t.clients in sync; register a client for the primary team in tests
  3. Verify the API key has label-read access to the primary team
  4. Add a pre-flight check for t.clients[primary] != nil before calling BatchPush

Example fix

// before
teamIDs := []string{"ENG"}; t.SetTeamIDs(teamIDs) // no client for ENG
// after
t.Init(ctx, cfg) // ensures clients (and thus caches) exist for primary team
result, err := t.BatchPush(ctx, issues, nil)
Defensive patterns

Strategy: validation

Validate before calling

primary := tracker.PrimaryTeamID()
if primary == "" || tracker.ClientForTeam(primary) == nil {
    return errors.New("primary Linear team is not initialized; cannot batch push")
}

Try / catch

result, err := tracker.BatchPush(ctx, issues, forceIDs)
if err != nil && strings.Contains(err.Error(), "no cache for primary team") {
    // re-init to rebuild clients and caches, then retry once
    _ = tracker.Init(ctx, cfg)
    result, err = tracker.BatchPush(ctx, issues, forceIDs)
}

Prevention

When it happens

Trigger: BatchPush called where t.teamIDs[0]'s entry was skipped because t.clients[teamIDs[0]] is nil, or BuildLabelCache silently never ran for the primary team — leaving teamLabelCaches[teamIDs[0]] unset.

Common situations: Mirrors the primary-team state-cache failure: partially initialized tracker, primary team client missing, tests that set teamIDs without registering the primary client, credential scoping that excludes the primary team.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/d1b7a235f9cfc12c. Report an issue: GitHub.