gastownhall/beads · warning

GitLab epic milestone sync: %v

Error message

GitLab epic milestone sync: %v

What it means

This warning is emitted by pushGitLabDependencyLinks (cmd/bd/gitlab.go:698) after gt.PushEpicMilestones completes with per-issue errors. During `bd gitlab sync` or `bd gitlab push`, beads tries to repair epic-child milestones on GitLab (set the GitLab milestone matching the epic on each scoped issue). Any error the GitLab API or local lookup returns for a milestone update is collected in the returned `errs` slice and printed as this warning; the sync continues rather than aborting.

Source

Thrown at cmd/bd/gitlab.go:698

		}
		for _, err := range res.Errors {
			warn(fmt.Sprintf("GitLab dependency link sync: %v", err))
		}
	}

	if len(linkData.ScopedIssues) > 0 {
		count, errs := gt.PushEpicMilestones(ctx, linkData.ScopedIssues, gitlab.EpicMilestoneOptions{
			DryRun: dryRun,
			OnPlan: func(issueID string, issueIID int, milestoneID int) {
				if !jsonOutput {
					_, _ = fmt.Fprintf(out, "  [dry-run] Would set GitLab milestone %d on %s (#%d)\n",
						milestoneID, issueID, issueIID)
				}
			},
		})
		milestonesUpdated = count
		for _, err := range errs {
			warn(fmt.Sprintf("GitLab epic milestone sync: %v", err))
		}
	}

	return linksPushed, linksLicenseSkipped, milestonesUpdated
}

type gitlabLinkSyncData struct {
	ScopedIssues []*types.Issue
	DesiredLinks []gitlab.DependencyLink
}

func collectGitLabLinkSyncData(ctx context.Context, st storage.Storage, opts tracker.SyncOptions) (gitlabLinkSyncData, []string) {
	if st == nil {
		return gitlabLinkSyncData{}, []string{"GitLab dependency link sync skipped: database not available"}
	}

	allIssues, err := st.SearchIssues(ctx, "", types.IssueFilter{})
	if err != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-run `bd gitlab sync` to see the full underlying error in the warning and check GitLab project/group access with the configured token.
  2. Verify the milestone referenced by the epic still exists in GitLab (or re-link the epic so a fresh milestone ID is fetched).
  3. Confirm the token has api write scope and the epic/child issue are in a project the token can modify.
  4. If a GitLab tier changed (Premium features lost), restore the tier or stop expecting epic-milestone repair for those links.
  5. Re-run the sync after fixing; the pass is additive/resumable, so previously succeeded issues are skipped.

Example fix

// before: stale milestone recorded on the epic, GitLab returns 400
GitLab epic milestone sync: PUT https://gitlab.com/api/v4/projects/42/issues/17: 400 {"milestone":[{"error":"does not exist"}]}
// after: recreate/repair milestone in GitLab (or re-link epic) then re-run
bd gitlab sync
GitLab epic milestone sync: no errors (milestone 9 set on bd-123 (#17))
Defensive patterns

Strategy: fallback

Validate before calling

// before bd gitlab push/sync
gitlab_project=$(git remote get-url origin | sed 's#.*gitlab.com[:/]##; s#\.git$##')
curl -sf -H "PRIVATE-TOKEN: $GITLAB_TOKEN" "https://gitlab.com/api/v4/projects/$(python3 -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1],safe=""))' "$gitlab_project")" >/dev/null || echo 'GitLab project/token not writable — fix before pushing links/milestones'

Try / catch

// callers of pushGitLabDependencyLinks cannot catch per-issue errors (they are warned, not returned);
// treat milestonesUpdated < expected as the failure signal:
if milestonesUpdated < expected {
    fmt.Fprintf(os.Stderr, "epic milestone sync incomplete: %d/%d; re-run bd gitlab sync after fixing GitLab access\n", milestonesUpdated, expected)
}

Prevention

When it happens

Trigger: Running `bd gitlab sync` or `bd gitlab push` with scoped issues whose epic milestone needs repairing, and PushEpicMilestones fails for one or more issues — e.g. the GitLab API rejects the milestone update (milestone ID no longer exists, milestone belongs to a different group/project), the epic or child issue was deleted remotely, the token lacks write scope, or an epic-child/milestone lookup returns 404.

Common situations: GitLab tier downgrades or moving epics between groups so the recorded milestone ID is invalid; stale milestone IDs after remote cleanup; expired/insufficiently-scoped PAT; milestone deleted in GitLab while beads still references it; network/5xx errors during the milestone PUT.

Related errors


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