multica-ai/multica · error
connect to daemon: %w
Error message
connect to daemon: %w
What it means
The first "connect to daemon" error site: client.Do(req) failed while POSTing to http://127.0.0.1:$MULTICA_DAEMON_PORT/repo/checkout. This is a transport-level failure — connection refused, no route, or the context deadline (5 minutes) expiring during the request itself. The retry loop only re-issues on HTTP 503 with X-Multica-Retryable: repo-busy, so transport errors abort immediately.
Source
Thrown at server/cmd/multica/cmd_repo.go:386
parentCtx := cmd.Context()
if parentCtx == nil {
parentCtx = context.Background()
}
ctx, cancel := context.WithTimeout(parentCtx, 5*time.Minute)
defer cancel()
client := &http.Client{}
checkoutURL := fmt.Sprintf("http://127.0.0.1:%s/repo/checkout", daemonPort)
var body []byte
for {
req, err := http.NewRequestWithContext(ctx, http.MethodPost, checkoutURL, bytes.NewReader(data))
if err != nil {
return fmt.Errorf("create daemon checkout request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("connect to daemon: %w", err)
}
body, err = io.ReadAll(resp.Body)
closeErr := resp.Body.Close()
if err != nil {
return fmt.Errorf("read daemon checkout response: %w", err)
}
if closeErr != nil {
return fmt.Errorf("close daemon checkout response: %w", closeErr)
}
if resp.StatusCode == http.StatusServiceUnavailable && resp.Header.Get("X-Multica-Retryable") == "repo-busy" {
delay := repoCheckoutRetryDelay(resp.Header.Get("Retry-After"), time.Now())
timer := time.NewTimer(delay)
select {
case <-ctx.Done():
timer.Stop()
return fmt.Errorf("connect to daemon: %w", context.Cause(ctx))
case <-timer.C:
continueView on GitHub (pinned to 2c0912b6ec)
Solutions
- Confirm the daemon is up and listening on the expected port: ss -ltnp | grep <port> or curl http://127.0.0.1:<port>/health.
- If the daemon restarted with a new port, re-run the command in a fresh daemon task so MULTICA_DAEMON_PORT is re-injected.
- If checkouts legitimately take >5 min, raise the context timeout in the CLI or reduce the checkout scope (smaller repo/ref) — note the timeout is hardcoded to 5*time.Minute.
- Check the message chain: "connection refused" means no listener; "context deadline exceeded" means timeout.
Example fix
# before: stale port from an old daemon MULTICA_DAEMON_PORT=8123 multica repo checkout URL # connection refused # after: verify listener, re-run inside a live daemon task ss -ltnp | grep 8123 # nothing? restart daemon / rerun task
Defensive patterns
Strategy: retry
Validate before calling
# fail fast if nothing listens on the daemon port before the long command
nc -z 127.0.0.1 "$MULTICA_DAEMON_PORT" || { echo 'daemon not listening' >&2; exit 1; } Try / catch
resp, err := client.Do(req)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
// 5-min budget exhausted mid-request: retry with a fresh context or bail
}
return fmt.Errorf("connect to daemon: %w", err)
} Prevention
- Health-check the daemon port before invoking checkout.
- Re-run commands inside fresh daemon tasks after daemon restarts so env stays correct.
- Keep checkouts under the hardcoded 5-minute context budget or shrink the clone.
When it happens
Trigger: Nothing listening on 127.0.0.1:$MULTICA_DAEMON_PORT (daemon not running or different port); daemon crashed between env injection and the call; wrong port value; the 5-minute ctx timeout elapsing while the request is in flight.
Common situations: Agent outlives its daemon (daemon restarted, old port captured in env); port mismatch after daemon reconfig; localhost unreachable in a network-namespace-restricted sandbox; very slow checkouts exceeding the 5-minute budget.
Related errors
- install Private Plugin: %w
- read daemon checkout response: %w
- checkout failed: %s
- list skills: %w
- create skill: %w
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/09218beb646fa42e.
Report an issue: GitHub.