multica-ai/multica · error

refresh workspace repos: %w

Error message

refresh workspace repos: %w

What it means

The daemon's repo-access check wraps a failed call to refreshWorkspaceRepos — the server API call that lists a workspace's configured repositories failed (network error, 5xx, or auth expiry). Downstream logic needs that list to decide whether a requested repoURL is allowed, so the transport failure is surfaced rather than treated as 'not configured'.

Source

Thrown at server/internal/daemon/daemon.go:3370

	//
	//   - cacheHitOnEntry=false but cache hit *after* we acquire the mutex:
	//     a sibling goroutine on a concurrent cold-miss already refreshed
	//     and populated the cache. We can skip the duplicate refresh — the
	//     sibling's refresh is fresh enough for our gate read.
	cacheHitOnEntry := d.workspaceRepoAllowed(workspaceID, repoURL) && d.repoCache.Lookup(workspaceID, repoURL) != ""

	if err := ws.repoRefreshMu.Lock(ctx); err != nil {
		return err
	}
	defer ws.repoRefreshMu.Unlock()

	if !cacheHitOnEntry && d.workspaceRepoAllowed(workspaceID, repoURL) && d.repoCache.Lookup(workspaceID, repoURL) != "" {
		return nil
	}

	resp, err := d.refreshWorkspaceRepos(ctx, workspaceID)
	if err != nil {
		return fmt.Errorf("refresh workspace repos: %w", err)
	}

	if !d.workspaceRepoAllowed(workspaceID, repoURL) {
		return ErrRepoNotConfigured
	}

	if d.repoCache.Lookup(workspaceID, repoURL) != "" {
		return nil
	}

	d.syncWorkspaceReposContext(ctx, workspaceID, resp.Repos)
	if err := ctx.Err(); err != nil {
		return context.Cause(ctx)
	}

	if d.repoCache.Lookup(workspaceID, repoURL) != "" {
		return nil
	}

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Check server reachability (curl the /api health endpoint) and the daemon's connectivity, then retry — this is usually transient
  2. If auth-related, re-run 'multica login' and restart the daemon so the token refreshes
  3. Look at the wrapped error's cause: a 5xx means server-side; a dial error means network/DNS
  4. If it persists only for one workspace, check that workspace's repo configuration server-side
Defensive patterns

Strategy: retry

Validate before calling

// Cheap reachability probe before the repo-permission path.
if err := pingServer(ctx, c.client, 2*time.Second); err != nil {
    return fmt.Errorf("server unreachable, skipping repo check: %w", err)
}

Try / catch

Retry with backoff around the wrapped call: unwrap the cause, retry only transient classes (net errors, 502/503/504, context deadline), and fail permanently on auth errors with a login hint.

Prevention

When it happens

Trigger: Any task/clone path that goes through repo-permission checking while the server is unreachable, returns 500/503, or the daemon's token expired — i.e. refreshWorkspaceRepos returns err and the repo cache has no hit for the workspace.

Common situations: Server outages or deploys, daemon hibernating through laptop sleep with stale connections, expired PAT after the renewal window was missed, and local firewall/DNS failures.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/60b92834e491f5e3. Report an issue: GitHub.