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
- Re-run `bd gitlab sync` to see the full underlying error in the warning and check GitLab project/group access with the configured token.
- Verify the milestone referenced by the epic still exists in GitLab (or re-link the epic so a fresh milestone ID is fetched).
- Confirm the token has api write scope and the epic/child issue are in a project the token can modify.
- If a GitLab tier changed (Premium features lost), restore the tier or stop expecting epic-milestone repair for those links.
- 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
- Keep the GitLab PAT api-scoped and rotate before expiry.
- Re-link epics after moving them between groups/projects so recorded milestone IDs stay valid.
- Run `bd gitlab sync --dry-run` first to surface milestone failures without writes.
- Watch for GitLab tier changes that alter epic/milestone behavior.
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
- API error: %s (status %d)
- failed to fetch issues: %w
- failed to fetch issues since %s: %w
- GraphQL error: %s
- failed to fetch issues since %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c6eedf1fe9ac60ba.
Report an issue: GitHub.