gastownhall/beads · error

dolt push failed: %w Output: %s

Error message

dolt push failed: %w
Output: %s

What it means

Push() shells out to `dolt push origin main` inside the cached clone and wraps the command's error plus its combined stdout/stderr output. This means dolt itself rejected the push — the local clone could not be pushed to the remote. The wrapped Output text carries dolt's own diagnostic (auth failure, non-fast-forward, network error, etc.).

Source

Thrown at internal/remotecache/cache.go:151

	return entry, nil
}

// Push pushes local commits in the cached clone back to the remote.
func (c *Cache) Push(ctx context.Context, remoteURL string) error {
	target := c.cloneTarget(remoteURL)
	if !c.doltExists(target) {
		return fmt.Errorf("no cached clone for %s", remoteURL)
	}

	lock, err := c.acquireLock(ctx, remoteURL)
	if err != nil {
		return fmt.Errorf("failed to acquire cache lock: %w", err)
	}
	defer c.releaseLock(lock)

	cmd := doltCmd(ctx, target, "push", "origin", "main")
	if output, err := cmd.CombinedOutput(); err != nil {
		return fmt.Errorf("dolt push failed: %w\nOutput: %s", err, output)
	}

	// Update push timestamp
	meta := c.readMeta(remoteURL)
	meta.LastPush = time.Now().UnixNano()
	c.writeMeta(remoteURL, meta)

	return nil
}

// OpenStore opens a DoltStorage from the cached clone using the provided
// StoreOpener. The cache entry directory is used as the beads directory.
// The caller is responsible for calling Close() on the returned store.
//
// Note: OpenStore does not acquire a cache lock. The caller must ensure
// no concurrent Ensure() or Push() is running against the same remoteURL,
// as those modify the underlying dolt database. This is safe for single-
// process CLI use but not for concurrent multi-process access.

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped `Output:` section — dolt's message identifies the actual cause (auth, non-fast-forward, network).
  2. If non-fast-forward: run Ensure() first to pull, merge fast-forward, then Push().
  3. Refresh credentials: set DOLT_REMOTE_USER/DOLT_REMOTE_PASSWORD or run `dolt creds use`/`dolt login`.
  4. Verify the remote is reachable and correct: `dolt ls-remote <url>` or check the URL in your bd config.
  5. If the clone is corrupted, `Evict(remoteURL)` and Ensure() to re-clone.

Example fix

// before: push without ensuring the clone is fresh
if err := cache.Push(ctx, remoteURL); err != nil { return err }
// after: pull first, then push
if _, err := cache.Ensure(ctx, remoteURL); err != nil { return err }
if err := cache.Push(ctx, remoteURL); err != nil { return err }
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := exec.LookPath("dolt"); err != nil {
    return fmt.Errorf("dolt CLI required")
}
if err := remotecache.ValidateRemoteURL(remoteURL); err != nil {
    return err
}

Try / catch

if err := cache.Push(ctx, url); err != nil {
    var doltOutput string
    if i := strings.Index(err.Error(), "Output:"); i >= 0 {
        doltOutput = err.Error()[i:]
    }
    switch {
    case strings.Contains(doltOutput, "unexpected client error: unauthorized"),
         strings.Contains(doltOutput, "authentication"):
        return fmt.Errorf("refresh dolt credentials (DOLT_REMOTE_USER/DOLT_REMOTE_PASSWORD or dolt creds): %w", err)
    case strings.Contains(doltOutput, "Non-Fast-Forward"):
        if _, err := cache.Ensure(ctx, url); err != nil { return err }
        return cache.Push(ctx, url)
    }
    return err
}

Prevention

When it happens

Trigger: Cache.Push(ctx, remoteURL) runs dolt push and it exits non-zero: remote is ahead (non-fast-forward), missing/invalid credentials (DOLT_REMOTE_USER/DOLT_REMOTE_PASSWORD/dolt creds), unreachable remote, remote branch protection, or a corrupted local clone.

Common situations: Expired Dolthub credentials; pushing without pulling first so origin/main has commits the clone lacks; offline or VPN-required networks; remote repo deleted or renamed; wrong URL typed in config.

Related errors


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