gastownhall/beads · warning

Failed to preview push %s in %s: %s

Error message

Failed to preview push %s in %s: %s

What it means

This is a warning emitted by the push engine's dry-run (preview) path when the tracker adapter's BatchPushDryRun returned a per-issue error entry in batchResult.Errors. The engine does not abort; it logs the failure for the specific local issue (item.LocalID) against the external tracker's display name and continues with the rest of the batch. It means one issue in your preview could not be simulated — e.g. validation or API lookup failed for that item only.

Source

Thrown at internal/tracker/engine.go:993

		stats.Skipped += skipped
		if len(pushIssues) == 0 {
			return stats, nil
		}
		if opts.DryRun {
			if dryRunner, ok := e.Tracker.(BatchPushDryRunner); ok {
				batchResult, err := dryRunner.BatchPushDryRun(ctx, pushIssues, forceIDs)
				if err != nil {
					return nil, fmt.Errorf("previewing batch push: %w", err)
				}
				e.renderBatchDryRun(pushIssues, batchResult)
				stats.Created += len(batchResult.Created)
				stats.Updated += len(batchResult.Updated)
				stats.Skipped += len(batchResult.Skipped)
				stats.Errors += len(batchResult.Errors)
				stats.Warnings = append(stats.Warnings, batchResult.Warnings...)
				for _, item := range batchResult.Errors {
					if item.LocalID != "" {
						e.warn("Failed to preview push %s in %s: %s", item.LocalID, e.Tracker.DisplayName(), item.Message)
						continue
					}
					e.warn("Failed to preview pushes in %s: %s", e.Tracker.DisplayName(), item.Message)
				}
				return stats, nil
			}
		} else {
			batchResult, err := batchTracker.BatchPush(ctx, pushIssues, forceIDs)
			if err != nil {
				return nil, fmt.Errorf("batch pushing issues: %w", err)
			}
			e.applyBatchPushResult(ctx, batchResult)
			stats.Created += len(batchResult.Created)
			stats.Updated += len(batchResult.Updated)
			stats.Skipped += len(batchResult.Skipped)
			stats.Errors += len(batchResult.Errors)
			stats.Warnings = append(stats.Warnings, batchResult.Warnings...)
			for _, item := range batchResult.Errors {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the %s message in the warning to see which item failed; fix that issue's data (title length, state, external_ref) locally and re-run the dry-run.
  2. Verify the remote tracker configuration (states, labels, project/board IDs) matches what the local issues reference.
  3. If the external_ref is stale, clear it or use force-push IDs so the item is treated as a create instead of an update.
  4. Check the adapter implementation's BatchPushDryRun to confirm why it returned a per-item error instead of skipping.

Example fix

// before: stale external_ref fails preview update
issue.ExternalRef = "github:does-not-exist-999"
// after: reset ref so preview treats it as a create
issue.ExternalRef = "" // or re-link to the correct remote issue
Defensive patterns

Strategy: validation

Validate before calling

// Before dry-run/push, sanity-check each issue that will be sent:
func validateForPush(issue *types.Issue) error {
    if issue.Title == "" || len(issue.Title) > 256 {
        return fmt.Errorf("issue %s: title missing or too long", issue.ID)
    }
    if issue.ExternalRef != "" && !tracker.IsExternalRef(issue.ExternalRef) {
        return fmt.Errorf("issue %s: stale external_ref %q", issue.ID, issue.ExternalRef)
    }
    return nil
}

Type guard

func hasBatchItemLocalID(item BatchErrorItem) bool { return item.LocalID != "" } // non-empty LocalID => per-issue diagnostics available

Try / catch

stats, err := engine.Sync(ctx, opts)
if err != nil {
    return fmt.Errorf("sync aborted: %w", err)
}
for _, w := range stats.Warnings { // preview item failures land here
    log.Warnf("preview warning: %s", w)
}
if stats.Errors > 0 { /* inspect and fix named issues, then re-run */ }

Prevention

When it happens

Trigger: Running a dry-run push (opts.DryRun=true) against a tracker implementing BatchPushDryRunner where BatchPushDryRun succeeds overall but returns an error item with a non-empty LocalID — e.g. the tracker API rejected that one issue during the preview (invalid state/label, missing external ref resolution, per-item validation).

Common situations: Previewing `bd sync --dry-run` against GitHub/Linear/Jira where one issue references a state or label that doesn't exist remotely, an issue's external_ref points to a deleted remote item, or a per-issue field violates the tracker's limits (title length, missing required field).

Related errors


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