gastownhall/beads · info

dry-run: would compact %s (original size: %d bytes)

Error message

dry-run: would compact %s (original size: %d bytes)

What it means

When Config.DryRun is true, CompactTier1 does not perform real compaction. Instead it returns this formatted message as an error to signal what WOULD happen: the issue ID and the computed original size (description + design + notes + acceptance criteria bytes). It is an informational sentinel, not a failure.

Source

Thrown at internal/compact/compactor.go:114

		return fmt.Errorf("failed to verify eligibility: %w", err)
	}
	if !eligible {
		if reason != "" {
			return fmt.Errorf("issue %s is not eligible for Tier 1 compaction: %s", issueID, reason)
		}
		return fmt.Errorf("issue %s is not eligible for Tier 1 compaction", issueID)
	}

	issue, err := c.store.GetIssue(ctx, issueID)
	if err != nil {
		return fmt.Errorf("failed to fetch issue: %w", err)
	}

	// Calculate original size
	originalSize := len(issue.Description) + len(issue.Design) + len(issue.Notes) + len(issue.AcceptanceCriteria)

	if c.config.DryRun {
		return fmt.Errorf("dry-run: would compact %s (original size: %d bytes)", issueID, originalSize)
	}

	// Get summary from AI
	summary, err := c.summarizer.SummarizeTier1(ctx, issue)
	if err != nil {
		return fmt.Errorf("failed to summarize: %w", err)
	}

	// Check if compaction would actually reduce size
	compactedSize := len(summary)
	if compactedSize >= originalSize {
		warningMsg := fmt.Sprintf("Tier 1 compaction skipped: summary (%d bytes) not shorter than original (%d bytes)", compactedSize, originalSize)
		if err := c.store.AddComment(ctx, issueID, "compactor", warningMsg); err != nil {
			return fmt.Errorf("failed to record warning: %w", err)
		}
		return fmt.Errorf("compaction would increase size (%d → %d bytes), keeping original", originalSize, compactedSize)
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Treat this return value as an expected dry-run report, not a failure, in batch aggregation logic
  2. Set a valid API key and DryRun: false to perform real compaction
  3. Check the log for the 'failed to create Haiku client' downgrade if dry-run was unintended
  4. Parse the original size from the message if you need reporting

Example fix

// before
cfg := &compact.Config{} // DryRun defaults false, but empty key downgrades silently
// after
cfg := &compact.Config{DryRun: false}
c, err := compact.New(store, os.Getenv("ANTHROPIC_API_KEY"), cfg)
if err != nil { return err }
if c.IsDryRun() { log.Println("warning: running in dry-run mode") }
Defensive patterns

Strategy: type-guard

Validate before calling

// detect dry-run before doing work
c, err := compact.New(store, key, cfg)
if err != nil { return err }
if cfg.DryRun { log.Println("compactor is in dry-run mode") }

Type guard

func inDryRun(cfg *compact.Config) bool { return cfg != nil && cfg.DryRun }

Try / catch

if err := c.CompactTier1(ctx, id); err != nil {
    if strings.Contains(err.Error(), "dry-run: would compact") {
        return nil // expected dry-run report
    }
    return err
}

Prevention

When it happens

Trigger: Calling CompactTier1 (directly or via runCompactSingle/batch) with a Compactor built with DryRun: true — including the automatic downgrade in New when no API key is present (errAPIKeyRequired path).

Common situations: Running `bd compact --dry-run`; forgetting to set an API key so New silently switched to dry-run; CI jobs without secrets that expect real compaction.

Related errors


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